Older Version Newer Version

JanetTerra JanetTerra Jul 22, 2006 - "Needs a link to Plot3D.bas"

==Easy Functions for Plotting 3D Objects== ===Tomas J. Nally [[user:steelweaver52]]=== //This preliminary article originally appeared in the **[[http://babek.info/libertybasicfiles/lbnews/nl113/plot3d.htm|Liberty BASIC Newsletter, Issue #113]]**. This article is not technically a part of Tom's **[[LBWFCh01|Liberty BASIC Wire Frame Library]]**, but this article did serve as the impetus for **[[LBWFCh01|LBWF Library]]**. Because this article is referenced in the **[[LBWFCh01|LBWF Library]]** series, it was thought best to include this article as part of the series. **Easy Functions for Plotting 3D Objects** is reprinted here with the permission of the author.// ---------- View the [[Plot3DSourceCode|source code]] for the functions described in this article! ---------- ===Making Humble CAD Technology Usable=== In late 2002 I published version 1.0 of **Humble CAD**, which is a [[http://www.libertybasic.com|Liberty Basic]] program for drawing "wire model images" of 3D objects. The reaction was favorable among [[http://www.libertybasic.com|Liberty Basic]] users, and I published versions 1.5 and 1.5.1 in early 2003. The latter version is available for download at two locations: [[http://lbdownloads.com/Uti.htm|LB Downloads]], and the [[http://groups.yahoo.com/group/libertybasic/files/|files area of the Liberty BASIC Yahoo group (HumCAD151.zip)]]. All versions of Humble CAD have been released as open source. [[image:HumbleCADPic01.jpg]] //Screenshot: HumbleCAD v1.5.1// But, just because the source code is "open" doesn't mean that the code is easy to extract and decipher for use in one's own programs. In fact, the most interesting part of Humble CAD's code--the vector math that converts all of the 3D data into //ready-to-plot// 2D format--is a little too disorganized and complex to be extracted for use in someone else's programs. The open source advantage, then, is wasted. Humble CAD contains good technology, but the accessibility to this technology is poor. This article and demo attempts to correct this lack of accessibility to Humble CAD's code. Specifically, two functions are provided with this article--**ScreenX()** and **ScreenY()** [[Plot3DSourceCode|(source code availabe here)]] --which accept coordinates of points in 3D space, and return the equivalent 2D screen coordinates of the same point. Please be aware that numerous arguements must be passed to these functions in order for them to work properly. As you read below, however, I'm sure you will appreciate the logic and necessity of this. ===The Arguments Required by ScreenX() and ScreenY()=== **ScreenX()** and **ScreenY()** each require twelve arguments. In fact, both functions require the //exact same arguments//! The only difference between the functions is that one returns the X-coordinate of the 3D point's projection onto the //LB GRAPHICBOX//, while the other returns the Y-coordinate. The only reason why two functions are required is because a function only returns a single value. If we could persuade a function to return two values, then this operation could be accomplished with a single function. Without further ado, here is a list of the twelve arguments required by **ScreenX()** and **ScreenY()**. It will be followed by a discussion of the importance of these arguments. > 1. XX - The X-coordinate of the node in space. > 2. YY - The Y-coordinate of the node in space. > 3. ZZ - The Z-coordinate of the node in space. > 4. CamX - (Think "Camera-X") The X-coordinate of the camera. > 5. CamY - (Think "Camera-Y") The Y-coordinate of the camera. > 6. CamZ - (Think "Camera-Z") The Z-coordinate of the camera. > 7. CtrX - (Think "Center-X") The X-coordinate of the point in space where your camera is pointed. I often call this point the "Viewing Center". > 8. CtrY - (Think "Center-Y") The Y-coordinate of the point in space where your camera is pointed. > 9. CtrZ - (Think "Center-Z") The Z-coordinate of the point in space where your camera is pointed. > 10. ScrCtrX - (Think "Screen Center-X") The X-coordinate of the GRAPHICBOX point which corresponds to the Viewing Center. > 11. ScrCtrY - (Think "Screen Center-Y") The Y-coordinate of the GRAPHICBOX point which corresponds to the Viewing Center. > 12. Scale - A value that allows you to apply "size control" to the plotted objects in the LB GRAPHICBOX. ===Arguments XX, YY and ZZ=== [[image:P3DPic01.jpg]] These three variables are the X-, Y-, and Z-coordinates of the //**node**// in space that we wish to plot. Understand, though, that plotting a single //**node**// by itself has little or no value. In this particular demo, the importance of a //**node**// is that it serves as one of the two endpoints of a //**line**//. The value of a //**line**// is that we can arrange numerous //**lines**// in space to make representations of objects. For instance, we can arrange 8 //**lines**// in space to form a pyramid. Four //**lines**// would form the square base of the pyramid, while the remaining for four //**lines**// would extend from the corners of the base up to the apex of the pyramid. ===Arguments CamX, CamY and CamZ=== [[image:P3DPic02.jpg]] These three variables are the X-, Y-, and Z-coordinates of the **camera location**. The camera location is the point in space where we view our objects. You can also think of it as the location of your **eye**. On other occasions, I've named these same variables **Xeye**, **Yeye** and **Zeye**. However, it looks like the convention is to refer to this point as the camera location rather than your eye location. ===Arguments CtrX, CtrY and CtrZ=== These three variables are the X-, Y-, and Z-coordinates of the point in space where you are **pointing the camera**. I typically call this point the **viewing center**, or just the **center**. Often, though not always, you may want to point the camera at the geometric center of your collection of objects. ===Arguments ScrCtrX and ScrCtrY=== [[image:P3DPic03.jpg]] These two variables are the X- and Y-coordinates of that point in the {{LB GRAPHICBOX}} which corresponds to the **viewing center**. For instance, if you want your objects to appear centered in the {{GRAPHICBOX}}, then **ScrCtrX** and **ScrCtrY** should be the //**centerpoint**// of the {{GRAPHICBOX}}. That is, if your {{GRAPHICBOX}} is 400 x 400, then [[code format="vb"]] ScrCtrX = 200 and ScrCtrY = 200 [[code]] ===Argument Scale=== The usefulness of **ScreenX()** and **ScreenY()** would be limited if it did not allow you to plot objects that were very large in scale (say thousands of units long or tall) or very small in scale (less than a unit long or tall). The //**Scale**// variable gives you "size control" over the plot. Of course, you must experiment with the //**Scale**// value until your plots produce objects that are properly sized. //**Scale**// can also be used to {{zoom in}} and {{zoom out}} when plotting objects. ===OK, So What Does the Function Look Like When Used?=== Without listing the code of the functions themselves ([[Plot3DSourceCode|source code available here]]), the example below is just about the simplist implementation of **ScreenX()** and **ScreenY()** than can be developed. (Please note that code to setup the {{WINDOW}} and the {{GRAPHICBOX}} control is omitted.) In this little code snippet, the coordinates of two points in space are defined, followed by all the other input arguments of the functions. **ScreenX()** and **ScreenY()** are each called twice: once for the first //**node**// in space, once for the second //**node**// in space. Each time **ScreenX()** or **ScreenY()** is called, the function returns a screen coordinate. At the end of the snippet, a //**line**// is plotted using the screen coordinates returned by **ScreenX()** and **ScreenY()**. [[code format="vb"]] XX1 = 5 ' YY1 = 5 ' ZZ1 = 5 'Coordinates of the two XX2 = 100 'nodes in space YY2 = 100 ' ZZ2 = 100 ' CamX = 300 ' CamY = 300 'Coordinates of the camera in space CamZ = 300 ' CtrX = 5 'The "center", CtrY = 5 'Coordinates of the point where the CtrZ = 5 'camera is pointing ScrCtrX = 200 'Coordinates of the GRAPHICBOX point ScrCtrY = 200 'corresponding to the "center" Scale = 1 'Define the Scale Factor 'Send all of the arguments to the two functions for the FIRST node. 'sx1 and sy1 become the screen coordinates of Node 1. sx1 = ScreenX(XX1, YY1, ZZ1, CamX, CamY, CamZ, CtrX, CtrY, CtrZ, ScrCtrX, ScrCtrY, Scale) sy1 = ScreenY(XX1, YY1, ZZ1, CamX, CamY, CamZ, CtrX, CtrY, CtrZ, ScrCtrX, ScrCtrY, Scale) 'Send all of the arguments to the two functions for the SECOND node. 'sx2 and sy2 become the screen coordinates of Node 2. sx2 = ScreenX(XX2, YY2, ZZ2, CamX, CamY, CamZ, CtrX, CtrY, CtrZ, ScrCtrX, ScrCtrY, Scale) sy2 = ScreenY(XX2, YY2, ZZ2, CamX, CamY, CamZ, CtrX, CtrY, CtrZ, ScrCtrX, ScrCtrY, Scale) 'Draw a line in the GRAPHICBOX between (sx1,sy1) and (sx2,sy2) print #main.gbox1, "line "; sx1; " "; sy1; " "; sx2; " "; sy2 [[code]] ===Demonstration Program: "Plot3D.bas"=== [[image:P3DPic04.jpg]] OK, I admit that there is nothing impressive about plotting a single //**line**// in a {{GRAPHICBOX}}. As I indicated elsewhere, the significance of projecting //**nodes**// in 3D space onto a 2D plane is that //**nodes**// help define //**lines**//, and //**lines**// help define //**objects**//. To help illustrate the usefulness of **ScreenX()** and **ScreenY()**, I'm providing a [[http://www.libertybasic.com|Liberty Basic]] program called **Plot3D.bas**. This program provides 3 pre-built objects. The objects are built from 24 //**nodes**// and 36 //**lines**//. The window of the application provides a number of textboxes which will allow you to change the coordinates of the camera, the coordinates of the "center", the coordinates of the "screen center" and the scale. Begin experimenting by changing these values, one at a time, by small amounts. Then press the button that says {{RePlot Objects}}. Note how the image changes. ===Limitations of ScreenX() and ScreenY()=== **ScreenX()** and **ScreenY()** will not produce good output if the user places the camera in the midst of the objects (or inside of an object) which we are viewing. This is because **ScreenX()** and **ScreenY()** are not sophisticated enough to know which //**nodes**// are "behind" the camera and therefore shouldn't be plotted. If you wish to try it, start **Plot3D.bas** and place (CamX, CamY, CamZ) at (-5, 10, 5). Nothing will break, it will only produce bizarre output. That limitation aside, feel free to incorporate **ScreenX()** and **ScreenY()** into your own programs. Like //**Humble CAD**//, this code is provided as open source. ---------- View the [[Plot3DSourceCode|source code]] for the functions described in this article! ---------- Tom Nally Steelweaver52@aol.com ----------