Newbie questions about drawing primitives

Started by
9 comments, last by Evil Steve 17 years, 7 months ago
Hi, I'm trying to teach myself DirectX and am having some difficulty drawing some primitives (just a triangle at the moment). Here is the relevant code: IDirect3DVertexBuffer9 *g_list_vb = NULL; #define D3DFVF_SIMPLEVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE) struct customVertex { float x, y, z; DWORD colour; }; ... // create a vertex buffer so that we can draw some things pD3DDevice9->CreateVertexBuffer(3*sizeof(customVertex), D3DUSAGE_WRITEONLY, D3DFVF_XYZ, D3DPOOL_MANAGED, &g_list_vb, NULL); ... customVertex vertices[3]; void *vb_vertices; vertices[0].x = -1.0f; vertices[0].y = 0.0f; vertices[0].z = 0.0f; vertices[0].colour = 0xffff0000; vertices[1].x = 0.0f; vertices[1].y = 1.0f; vertices[1].z = 0.0f; vertices[1].colour = 0xff00ff00; vertices[2].x = 1.0f; vertices[2].y = 0.0f; vertices[2].z = 0.0f; vertices[2].colour = 0xff00ffff; // to fill the vertex buffer, we have to lock it first g_list_vb->Lock(0, 0, (void**)&vb_vertices, 0); // now copy the vertices in to the vertex buffer memcpy( vb_vertices, vertices, 3*sizeof(customVertex)); // unlock the vertex buffer g_list_vb->Unlock(); pD3DDevice9->SetStreamSource( 0, g_list_vb, 0, sizeof(customVertex) ); pD3DDevice9->SetFVF( D3DFVF_SIMPLEVERTEX ); // draw the triangle pD3DDevice9->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1); -------------------- Ok, my program displays a triangle, however it is completely black even though I am specifying colours. What's wrong there? Also, how do I convert the co-ordinates that I use for my vertices in to pixels (I don't like having to work with values between -1 and 1!)?
Advertisement
Quote:Original post by n000b
Ok, my program displays a triangle, however it is completely black even though I am specifying colours. What's wrong there?

Make sure that the D3DRS_LIGHTING render-state is off. Also, you can use the D3DCOLOR_ARGB() macro to generate DWORD colors more easily.

Quote:Also, how do I convert the co-ordinates that I use for my vertices in to pixels (I don't like having to work with values between -1 and 1!)?

Check out this Nexe article. You can always use D3DFVF_XYZRHW - ie vertices that are already in screen space.
Dustin Franklin ( circlesoft :: KBase :: Mystic GD :: ApolloNL )
You can convert pixel space coordinates [0, SCREEN_DIMENSION] to screen space [-1, 1] with a translation and scale:
screen_x = SCREEN_WIDTH * (pixel_x + 1) / 2;screen_y = SCREEN_HEIGHT * (pixel_y + 1) / 2;

and vica-versa with the inverse:
pixel_x = ((2 * screen_x) / SCREEN_WIDTH) - 1;pixel_y = ((2 * screen_y) / SCREEN_HEIGHT) - 1;

You may find it useful, if you aren't already using your world matrix, to simply set it to
SW/2  0     0     SW/20     SH/2  0     SH/20     0     1     00     0     0     1
This is essentially the same as the first pair of equations. With this at the top of your matrix stack, you can work in pixels without needing to think about dimensionless screen coordinates.

Regards
Admiral
Ring3 Circus - Diary of a programmer, journal of a hacker.
Thanks for the info, I will try it out soon :)

I think I've got another problem that I need to sort out first though.

I changed my code to the following to try and draw a square:


customVertex vertices[4];
void *vb_vertices;

vertices[0].x = -0.75f;
vertices[0].y = -0.75f;
vertices[0].z = 0.0f;
vertices[0].colour = 0xffff0000;

vertices[1].x = -0.75f;
vertices[1].y = 0.75f;
vertices[1].z = 0.0f;
vertices[1].colour = 0xff00ff00;

vertices[2].x = 0.75f;
vertices[2].y = 0.75f;
vertices[2].z = 0.0f;
vertices[2].colour = 0xffff0000;

vertices[3].x = 0.75f;
vertices[3].y = -0.75f;
vertices[3].z = 0.0f;
vertices[3].colour = 0xff00ffff;


// to fill the vertex buffer, we have to lock it first
g_list_vb->Lock(0,
0,
(void**)&vb_vertices,
0);


// now copy the vertices in to the vertex buffer
memcpy( vb_vertices,
vertices,
4*sizeof(customVertex));


// unlock the vertex buffer
g_list_vb->Unlock();


pD3DDevice9->SetStreamSource( 0, g_list_vb, 0, sizeof(customVertex) );

pD3DDevice9->SetFVF( D3DFVF_SIMPLEVERTEX );

// draw the triangle
pD3DDevice9->DrawPrimitive( D3DPT_TRIANGLESTRIP,
0,
2);

-------------------------

My program only displays the top left triangle though (ie a triangle between the top left, top right and bottom left vertices), it doesn't draw the other triangle though. Anyone know why?
You need to specify your vertices in the correct order, counter-clockwise triangles are culled by default. With triangle strips, the culling direction alternates for each triangle, so the first should have vertices in clockwise order, the second in CCW, the third in CW, etc.

The following order should work (Untested):
vertices[0].x = -0.75f;vertices[0].y = -0.75f;vertices[0].z = 0.0f;vertices[0].colour = 0xffff0000;vertices[1].x = 0.75f;vertices[1].y = -0.75f;vertices[1].z = 0.0f;vertices[1].colour = 0xff00ff00;vertices[2].x = -0.75f;vertices[2].y = 0.75f;vertices[2].z = 0.0f;vertices[2].colour = 0xffff0000;vertices[3].x = 0.75f;vertices[3].y = 0.75f;vertices[3].z = 0.0f;vertices[3].colour = 0xff00ffff;
Quote:Original post by Evil Steve
You need to specify your vertices in the correct order, counter-clockwise triangles are culled by default. With triangle strips, the culling direction alternates for each triangle, so the first should have vertices in clockwise order, the second in CCW, the third in CW, etc.

The following order should work (Untested):
*** Source Snippet Removed ***




I tried your code but it did not work. There may be something wrong in my other code - can someone look through my first post and confirm that my code is fine please?

Also, I don't understand what you mean about the triangle strips. After the first triangle for which you need all three vertices, don't you only need to define one vertice for each triangle after that? If so, how are you supposed to alternate the defining order for each triangle?
Quote:Original post by n000b
Also, I don't understand what you mean about the triangle strips. After the first triangle for which you need all three vertices, don't you only need to define one vertice for each triangle after that? If so, how are you supposed to alternate the defining order for each triangle?
Yes, every vertex you add makes a new triangle. The alternating vertex order is implicit. If you add a new vertex in the wrong place, you could end up with a back facing triangle, which will be culled.

Edit:
+--+--+--+--+|\2|\4|\6|\8||1\|3\|5\|7\|+--+--+--+--+

Triangles 1, 3, 5 and 7 have their vertices in clockwise order, 2, 4, 6 and 8 are anti-clockwise.
Quote:
Edit:
+--+--+--+--+|\2|\4|\6|\8||1\|3\|5\|7\|+--+--+--+--+

Triangles 1, 3, 5 and 7 have their vertices in clockwise order, 2, 4, 6 and 8 are anti-clockwise.



I still don't understand how you're supposed to draw the second triangle in alternating order.

To draw the first triangle, would you do it in this order: bottom right, bottom left, top left. Then would you just draw the top right one to make triangle 2?
Quote:Original post by n000b
Quote:
Edit:
+--+--+--+--+|\2|\4|\6|\8||1\|3\|5\|7\|+--+--+--+--+

Triangles 1, 3, 5 and 7 have their vertices in clockwise order, 2, 4, 6 and 8 are anti-clockwise.



I still don't understand how you're supposed to draw the second triangle in alternating order.

To draw the first triangle, would you do it in this order: bottom right, bottom left, top left. Then would you just draw the top right one to make triangle 2?

No. The three vertices for the second triangle will always be the last two vertices from the previous triangle, in the order that they were originally specified, with the fourth vertex added at the end. Thus, you'd do something like the bottom left, top left, and bottom right for the first triangle, and then you'd be forced to do the top left and bottom right to start the second triangle, followed finally by the top right. So if you follow the vertices in that order, you'll see that the second triangle is in the reverse order of the first. The third triangle will then use the bottom right, top right, and then the next vertex along the bottom, and so on.
"We should have a great fewer disputes in the world if words were taken for what they are, the signs of our ideas only, and not for things themselves." - John Locke
Thanks, I've got it working now! :)

A question though, every time I want to add another vertice, I need to change the size of the array in three places: when creating the array, when setting up the vertex buffer and when calling memcpy. Is there any way this value dynamic or anything so that it is easier to maintain? I know I can create a constant to hold the value so that I only have to change it in one place, it still seems a little annoying though.

Also, am I correct in thinking that you can only create on vertex buffer? If so, how would you display multiple seperate objects to the screen? Just say I wanted to draw three seperate squares, how would I do this using DrawPrimitive?

This topic is closed to new replies.

Advertisement