 Points Introduction In this lesson we are going to plot points defined in Screen Space. We'll generate 2 different data sets and plot them. We will also show some very basic input handling which will allow you to control which data set of points we'll plot. Defining our Vertices As mentioned in our 3D Primer, a point is defined by a single vertex. For our vertices we need a position, and RHW and to make things look more interesting, a colour. Here are our vertex definitions and our declaration of 2 arrays to hold our data. ```int g_width=640; //The width of our display struct point_vertex{ float x, y, z, rhw; // The transformed(screen space) position for the vertex. DWORD colour; // The vertex colour. }; const DWORD point_fvf=D3DFVF_XYZRHW|D3DFVF_DIFFUSE; point_vertex sine_data[g_width]; //Enough data to plot from one edge to the other point_vertex random_data[g_width]; ``` Initializing Data Since our points will be distributed on a flat plane, we won't really use the Z coordinate so we'll set it to 1.0. The rhw will also be set to 1.0 in each case. I won't go into a lot of detail about how I generate the data since it's not really important. Basically the first data set is a sine wave that's scaled and offset. The green channel of the points is determined by how close they are to the left edge, and the blue channel by their proximity to the right edge. The red channel is calculated from the magnitude (absolute value of the distance from the horizontal axis). Our second data set is just a bunch of random points with random colours. Here's the code to generate the second data set. ```int count; srand(GetTickCount()); for(count=0;countSetFVF(point_fvf); ``` When you set the FVF it stays current until another one is set. So this could be moved to the init_scene function. If the device is lost we'd have to reset it as well. I kept it in the render function to keep the code together in a more logical, if not completely practical, way. Next is the call that does the rendering. There are a variety of Draw calls, but the one we use here is DrawPrimitiveUP. The UP stands for User Pointer. In a later lesson (Vertex Buffers) I'll show you a more efficient way of storing your data, but for now this works well. Here's the prototype for the function. ```HRESULT DrawPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, unsigned int PrimitiveCount, const void *pVertexStreamZeroData, unsigned int VertexStreamZeroStride ); ``` PrimitiveType The type of primitive we'll be rendering. In this case it's a point list (D3DPT_POINTLIST). PrimitiveCount How many primitives to draw. Direct3D has no way of knowing how many primitives there are in our array. This can also be used to draw only a portion of the point list. pVertexStreamZeroData This is just a pointer to our vertex array. VertexStreamZeroStride This specifies the size in bytes of each vertex. After reading each vertex it needs to know how far to move forward to read the next one. Here's our call to DrawPrimitiveUP. ``` g_d3d_device->DrawPrimitiveUP(D3DPT_POINTLIST, //PrimitiveType g_width, //PrimitiveCount data, //pVertexStreamZeroData sizeof(point_vertex)); //VertexStreamZeroStride ``` We're drawing a Point List, and there are the same number of primitives as pixels across our display. We also pass in a pointer to our data and the size of each vertex. It couldn't be much simpler than that! Now when you run the example program you'll see a random scattering of coloured dots. Hitting 't' will toggle you between that dot cloud and the plotting of a Sine Wave. Feel free to tinker with the data to plot different shapes. Remember that if you change the size of the data set you have to change the array definition and the value passed to DrawPrimitiveUP. Lesson Downloads Source and Executable for C++ (85K) Source for C++ (9K) To compile this lesson you will also need the Drunken Hyena Common Code MSDN Links For Functions/Concepts Introduced Here Back