In the first article we did some basic 3D camera projection and rendered some particles. In this second article we will use the transformation matrix to move those points around in 3d Space and then we will work with a fundamental 3D shape, a shaded triangle. Since we were working with particles in the last article, we will now move those particles around using the transformation matrix to rotate scale and translate them in 3d space. A transformation matrix is a 4 by 4 array of values that is then multiplied by the coordinates of our points. The result is that our points can be scaled, rotated and translated with just multiplication and addition. No complex math is needed. Transformation matrixes are created by the Dogwaffle3D.MakeTransformationMatrix method. MakeTransformationMatrix(ByVal x As Single, ByVal y As Single, ByVal z As Single, ByVal heading As Single, ByVal pitch As Single, ByVal bank As Single, ByVal scalex As Single, ByVal scaley As Single, ByVal scalez As Single) As Variant The method returns a 4x4 array in a variant data type. once it is returned, if we wanted, we could read any of it's values like this: MyValue = Matrix(0,3) Once we have the matrix, we can multiply the coordinates of any of our points and to accomplish our rotation and scale. The 4th element of our matrix is the translation factor, and it's just added. The math for all this would look something like this. 'loop through all the points in the object, mutliplying them by the new matrix (and adding the translation) For n = 0 To count-1 'retrieve values of x,y,z for this point in space here. NewX = (x * newmatrix(0, 0)) + (y * newmatrix(0, 1)) + (z * newmatrix(0, 2)) + newmatrix(0, 3) NewY = (x * newmatrix(1, 0)) + (y * newmatrix(1, 1)) + (z * newmatrix(1, 2)) + newmatrix(1, 3) NewZ = (x * newmatrix(2, 0)) + (y * newmatrix(2, 1)) + (z * newmatrix(2, 2)) + newmatrix(2, 3) Next Now, suppose you want to rotate one object around another. That sounds a little scary. But all you need to do is create more than one transformation matrix, then combine them with the Dogwaffle3D.CombineMatrix method CombineMatrix(Matrix1 As Variant, matrix2 As Variant) As Variant This method takes two transformation matixes and combines them into one new one. Then the math simply proceeds at outlined above. It's like getting all those extra transforms for free and there's very little overhead because that matrix is only a 4x4 array. See the example project at --- For example if you wanted to rotate one object around another, you would make one transformaiton matrix to translate the object to the place where you want it, nother to rotate it, etc. Mind you, the order that you comine matrixes changes the final result. Triangles Now that we've covered the basics of 3D projection and some transormations, lets cover the basics of rendering. Howler supports a shaded triangle that can be used to render 3D objects. To use the shaded triangle, you will need to setup a zbuffer. This is used to store depth information. The zbuffer can be turned on with Dogwaffle3D.InitZbuffer. When we're done using it, it should be freed with dogwaffle3D.freeZbuffer. If for some reason we need to see the content of the zbuffer, it can be retreived with Dogwaffle3D.GetZbuffer. This method returns an array with the same dimensions the the screen (remeber Howler actually returns one dimension larger than what is specified by the width/height properties, for historical reasons) before we can use the zbuffer for rendering triangles, we should set a maximum value in it. Say our farthest point is 300 units away, we would set the zbuffer value to at least 300. It can be more. If its less, the triangles will be clipped to it. The value can be any value in the rane of a floating point value. We set a value in the zbuffer like this: Dogwaffle3D.FillZbuffer(300) Dogwaffle3D.ZbufferIsGood, by the way, returns true if the zbuffer has already be initialized if you need to know. Now that that's done we can render away. z traingles are the basic building block of a 3d object. The parameters are stored in a 2 dimensional array of type single. It can be initialized like this Dim Triangles(17, count) As Single There are eightteen parameters (17 is the upper bound (vb likes to do it that way for some reason)). Count is the number of traingles you would like to render. You can render more than one at a time, which is faster. It avoids making calles through the COM interface too often, which can be slow. If you wanted to render 1000 triangles at once, you would use Dim Triangles(17, 999) As Single The function call looks like this: Dogwaffle3D.DrawZTriangles(Triangles, 10) It's usually followed up with a screen refresh so we can see the results. Dogwaffle3D.Refresh() the parameters for the trianlges are as stored in the array as follows: 'x0,y0,z0,x1,y1,z1,x2,y2,z1,r1,g1,b1,r2,g2,b2,r3,g3,b3 here, the x and y are the z scaled coordinates (in our simple example, divided by z) and z is the actual z coordinate. x0,y0,x1,y1,x2,y2 are the 3 cooridinates of the points of the triangle. r0,g0,b0,r1,g1,b1,r2,g2,b2 are the colors of each point of the triangle. So in steps, rendering goes like this... initialize the zbuffer and fill it with a max value. initialize an array to hold your traingles loop through all your trianges { call x/z, y/z and z for each point of the triangle, along with the colors of each point of the triangle. } call DrawZTriangles call Dogwaffle3D.Refresh() to see the resuls Free the zbuffer (when totally done)