Personal C Sharp                                                         By  famsoft.org
HomeHow To StartExamples-DesktopExamples-WebPC# MethodsReference-DesktopReference-Web


=============================================================================================== USING THE WINDOWS PRESENTATION FOUNDATION (WPF) =============================================== We have now two seperate classes. Class (pcs) is for version 2. You can use it with either version 2 or version 3. Additionally, we have class (pcs3) which can be accessed with version 3 only. The two classes are identical in everything except Controls and Drawing. All version 3 additions will be in class (pcs3) only. Changes made to Controls: ========================= The (WPF) controls are more similar to the "Web Controls" than to the "Desktop" Controls. For this reason, class (pcs3) is using almost identical software to the one used in class (pasp) for this purpose. Class (pcs3) does not do the layout discretely, it does it in the same manner as class (pasp) does. ------------------------------------------------------------------- If you have not studied the "Web Examples" yet, you must study at least the first 4 examples of the "WPDI" before you get further. ------------------------------------------------------------------- Class (pasp) inserts each group of controls into a table, then inserts the tables into bigger tables, and this continues until it ends with the root table "tb0" containing the whole page. Class (pcs3) uses the same idea except that it replaces tables with panels called "Grids" which are very similar to tables. The root grid "gr0" contains everything in the page. Some of the good ideas used in class (pasp) like having a "Master page" and combining controls with graphics are going to be used also in class (pcs3) Although we have done the best we can to absorb the new changes internally into class (pcs3), so you can use the same PC# methods as if nothing has been changed, there are still some few changes which you need to be taking care of. As a sample, this is how example 1 of the chapter "Using Controls"is to be modified in order to run with class (pcs3) and the WPF: ---------------------------------------------------------------------------------------------- public class a : pcs3 { public override void init() { base.init(); } public override void setup() { // All installations are done within this method //---------------------------------- Page Contents ----------------------------------- cns=""; // gr0 has no container since it's the root cs="gr0";cls="S9g8";cm("i"); // gr0 installation parameters //----------------------------------- gr0 Contents ----------------------------------- cns="gr0"; cs="tf0";j=k=0;oyd=0.5;ds="c";lf=200;cls="b0y0";fns="trbi20";cm("i"); cs="bt0";cis="My Color Changes";j=0;k=1;oyd=0.5;ds="c";lf=160;of=30;fns="trb16"; cls="S9y0";cm("i"); } public override void update() { // This method is called whenever an event takes place if ("bt0".Equals(cs)) { // If button "bt0" has generated this event cs="tf0";cm("gu"); // Get latest update of text field "tf0" in (cus) if (cus.Length<1) return; os=cus.Substring(0,1);om("u");// Get 1st char of (cus) and covert it to U/C n="RGB".IndexOf(os); // See if it was R,G,B or none of them if (n<0) cls="S9y0"; // If none of them select yello background color else if (n==0) cls="S9r0"; // If was "R" select red background color else if (n==1) cls="S9g0"; // If was "G" select green background color else if (n==2) cls="S9b0"; // If was "B" select blue background color cs="bt0";cm("sC"); // Call method cm() to set the color for "bt0" cs="tf0";cus="";cm("su"); // Erase tf0's text. cs="tf0";cm("sx"); // Turn the focus state of "tf0" on. } } } ---------------------------------------------------------------------------------------------- Compiling: ========== You may compile the class with either the Visual Studio or tool (pcp) If you receive an error when you compile with our tool, select "PC# Reference-Desktop" and read the section titled "The refs.txt file" to learn how to correct the problem. ---------------------------------------------------------------------------------------------- As you can see, the code is mostly the same. You are still using the same methods, the same architecture, the same color and font codes. So, as far as you are concerned almost nothing has changed. The only difference, you may have noticed is using grids instead of tables. Using grids is similar only. Some rules are different since they require more complicated setup. We have done our best to simplify their setup and ended with dividing controls into 3 categories each require different actions. Let us list all setup parameters before we get further: j,k : Index of first cell which the control occupies horizontally and vertically. This has been explained in WPDI so we are not going to say more about these two parameters here. i,o : Column and row span. These two items have also been discussed thoroughly in WPDI. lf,of : Width and height of the control. oxd,oyd: They are new. When you like to install two controls into one grid panel horizontally, and the first contol is twice as wide as the second one, you need to make the assignments (oxd=0.67;) for the first one and (oxd=0.33;) for the second one. In general, for each control in the container: oxd = (Its CellWidth / ContainerWidth) oyd = (Its CellHeight / ContainerHeight) When we have been installing web controls into tables, the space allocation job has been done automatically. Unfortunately, Grid panels are less helpful with this feature. This is why we need these two parameters. ds : Direction string. Can be (c/n/s/e/w/ne/nw/se/sw/fh/fv) It tells how the control will be aligned inside its cell. (c) means center, Next 8 directional symbols are obvious. (fh) and (fv) mean that the control should fill its cell horizontally / vertically. Default values: --------------- As you know, when you keep a parameter unassigned, its value will be zero if numeric or "" if string. Here is what leaving each of the parameters unassigned mean: j,k : Means that the control starts at the first cell (horizontally, vertically) i,o : Means that the control ocupies one cell (horizontally, vertically) oxd,oyd : Means that the control occupies the full width or the full height of its container. ds : Means mount the control at the center of its cell. Let us now discuss each control category requirements: (1) Grids: ---------- As you can see in the code above, the root grid is installed first. Then you may need to install more grids into the root grid, then install additional grids into each of the new grids,... this may continue forming a tree of grids. The root grid requires no parameters other than the color if you like it to be identifiable. This is because,it is the only control in its container. Branch grids require j, k, i, o and either (lf,of) or (oxd,oyd) You may also supply both if you don't like the grid to occupy its entire cell (meaning that you like to keep a margin around it) (2) Image Controls: ------------------- The simplist way to mount an Image Control is to divide the space of its container by installing additional grids into it first, then installing the image control into one of the new grids. Since it will be the only control in its container, it will require no parameters other than (lf,of) if you like to change the size of its image. (3) All other controls: ----------------------- Supplying j, k, i, o, oxd and oyd is necessary for all other controls (unless you are accepting defaults) Assigning values to (lf, of) is optional. Creating a master page: ======================= As you have noticed with web controls, master pages offer a great help. So, let us have one which contains an icon, a title and a settable page number to be displayed. It will also contain the two public variables (PageWidth) and (PageHeight) which allow each page to set their useable page width and height if default values have not been acceptable. The master page class will extend class (pcs3) and each example class will extend the master page class. You can create a hierarchy of master pages and each may contain fields and methods which can be accessed by your application classes. --------------------------------------------------------------------------------------------- public class ms1:pcs3 { public int PageNumber=0; public int PageWidth=560; public int PageHeight=300; public override void setup() { base.setup(); //---------------------------------- Page Contents ----------------------------------- cns=""; // gr0 Container="" since it's // mounted directly into the page. cs="gr0";cls="S9s9";cm("i"); // gr0 installation parameters //----------------------------------- gr0 Contents ----------------------------------- cns="gr0"; // Container=gr0 for next grids cs="gr1";j=0;k=0;lf=PageWidth-150;of=60;ds="w";cls="S9g7";fns="tr12";jd=5;cm("i"); cs="gr2";j=1;k=0;lf=150;of=60;ds="e";cls="S9g7";fns="crb10";jd=5;cm("i"); cs="gr3";j=0;k=1;i=2;lf=PageWidth;of=PageHeight;ds="c";cls="S9y7";fns="crb10";cm("i"); //----------------------------------- gr2 Contents ---------------------------------- cns="gr1"; // gr1 is divided into 4 col,3 rows cs="lb11";j=0;k=0;oyd=0.6;ds="c";cis="Windows Presentation Foundation Examples"; fns="trb16";cls="r0g7";cm("i"); cs="lb12";j=0;k=1;oyd=0.4;ds="c";cis="Example Number "+PageNumber; fns="trb12";cls="b0g7";cm("i"); //----------------------------------- gr2 Contents ---------------------------------- cns="gr2"; // gr1 is divided into 4 col,3 rows cs="im01";j=0;k=0;ds="e";ims="images\\icon.bmp";cm("i"); } public class helper:pcs { } } ---------------------------------------------------------------------------------------------- The master page makes a good exercise on mounting controls. Here are some remarks: (1) We needed to create two grids one for common data at the top and one to be used by the child pages. Since we wanted to mount an image, we had to create a third grid for it. (2) For the grids we must supply either (lf,of) or (oxd,oyd) In this case, we supplied (lf,of) (3) (i,o) have been left unassigned for all except for the grid which will be used by child classes (gr3) since it occupies 2 cells horizontally. (4) For (lb11,lb12), (oxd) has not been assigned since they occupy their entire cell horizonty. ---------------------------------------------------------------------------------------------- Accessing class (pcs) graphics: ------------------------------- Version 2 has been great for graphics and we have spent plenty of time creating software using the ".NET" version 2 and both classes (pcs) and (pasp), so we must make use of them here. We have developed an easy way to access version 2 graphics which requires the following: (1) You install an Image Control which will receive (bio) with your drawing on. (2) You create a nested class which extends class (pcs). (3) You start the nested class by calling gm("wo") meaning "Open a new WPF operation". (4) You write the same code into the nested class just as you have been. (5) You end the nested class with calling gm("wc") meaning "Close the WPF operation. This will modify the resulting (bio) with all the graphics on its surface to meet WPF requirements. (5) From method run() of the top class you execute the nested class then call cm("su") supplying it with the image control's keyname. Method cm() at this mode updates an image control by changing its image. The method expects the new image file name to be assigned to (ims) This time we assign "b" to (ims) which means to the method that the image is (bio) --------------------------------------------------------------------------------------------- Example 1: Create a master page then extend it with a class which runs two examples of the version 2 kind. One is example 1 of "Handling controls" and the other is example 8 of "Drawing". --------------------------------------------------------------------------------------------- //assembly ms1.exe; // Referenced object. public class a : ms1 { // using pcs3 // Class a extends master class. public override void init() { base.init(); } public override void setup() { PageNumber=1;base.setup(); // Call Master Class's setup(), set Page No. //----------------------------------- gr3 Contents ----------------------------------- cns="gr3"; // gr3 is divided into 2 columns cs="gr4";cis="g1";j=0;k=0;oxd=0.5;ds="w";cls="S9y7";fns="tr12";cm("i"); cs="gr5";j=1;k=0;oxd=0.5;ds="e";cls="S9y7";fns="crb10";cm("i"); //----------------------------------- gr4 Contents ----------------------------------- cns="gr4"; cs="tf0";j=k=0;oyd=0.5;ds="c";lf=200;cls="b0y0";fns="trbi20";cm("i"); cs="bt0";cis="My Color Changes";j=0;k=1;oyd=0.5;ds="c";lf=160;of=30; fns="trb16";cls="S9y0";cm("i"); //----------------------------------- gr5 Contents ----------------------------------- cns="gr5"; cs="im1";ds="c";ims="";lf=200;of=200;cm("i"); } // This is the control which will receive (bio) and scale it //-------------- Method update is entirely used by color change section ---------------- public override void update() { // This method is called whenever an event takes place if ("bt0".Equals(cs)) { // If button "bt0" has generated this event cs="tf0";cm("gu"); // Get latest update of text field "tf0" in (cus) if (cus.Length<1) return; os=cus.Substring(0,1);om("u");// Get 1st char of (cus) and covert it to U/C n="RGB".IndexOf(os); // See if it was R,G,B or none of them if (n<0) cls="S9y0"; // If none of them select yello background color else if (n==0) cls="S9r0"; // If was "R" select red background color else if (n==1) cls="S9g0"; // If was "G" select green background color else if (n==2) cls="S9b0"; // If was "B" select blue background color cs="bt0";cm("sC"); // Call method cm() to set the color for "bt0" cs="tf0";cus="";cm("su"); // Erase tf0's text. cs="tf0";cm("sx"); // Turn the focus state of "tf0" on. } } //------------------- Method run is entirely used by the Drawing section --------------- public override void run() { N no=new N(); // Inistantiate nested class. no.run(); // Run nested class instance. cs="im1";ims="b";cm("su"); // Update Image control with (bio) image. } //--------------------------------- The nested class ----------------------------------- public class N : pcs { // Class (N) extends (pcs) public override void run() { gm("bwo"); // Open a new WPF operation j=k=220;cm("fs"); // Reduce size to fit object. cls="y7";gm("ec"); // Make background color matchs page's color. //********************** No change upto next asterisk line ************************* lf=of=170;gm("ce"); // Create the circular gold plate cls="o5y5";gm("spl"); // Prepare linear gradient brush for it gm("grf"); // then render-fill the gold plate. lf=6;of=50;gm("c="); // Create hexagon shape object at center. cls="r0";ks="r";gm("grs"); // Draw the object using sp effects-refl at jf=45;cls="b0";ks="r";gm("grs"); // center in red, then repeat 6 times using jf=-45;cls="b0";ks="r";gm("grs"); // different colors and different locations jf=22;kf=40;cls="g0";ks="r";gm("grs"); jf=-22;kf=40;cls="m0";ks="r";gm("grs"); jf=22;kf=-40;cls="m0";ks="r";gm("grs"); jf=-22;kf=-40;cls="g0";ks="r";gm("grs"); lf=of=25;gm("ce"); // Create a circle at center (pearl) for (int x=0;x<20;x++) { // Draw it 20 times using sp effects-reflection jf=80;kf=18*x;kb=true; // at locations around the plate. Polar coord's cls="p0";ks="r";gm("grs"); // are used for specifying locations } //*********************************************************************************** gm("bwc"); // Close WPF operation } } } ============================================================================================== Compiling: ========== You may compile the class with either the Visual Studio or tool (pcp) If you receive an error when you compile with our tool, select "PC# Reference-Desktop" and read the section titled "The refs.txt file" to learn how to correct the problem. Notice how the class declaration statement contains the word "pcs3" following a comment symbol. public class a : ms1 { // using pcs3 // Class a extends master class. When you compile a class using one PC# tool, the tool checks to see if your class extends class (pcs3) If it does, it reads the file "system\\Refs.txt" which is located into your working directory and adds all the locations it contains. This time your class extends class (ms1), but since (ms1) extends (pcs3), you want the tool to do the same. The tool is made to merely look for the availability of the word "pcs3" at the class declaration line in order to conclude whether to add the locations or not. So including the word "pcs3" into any commented phrase on the same line can make it do the same. ----------------------------------------------------------------------------------------------


BEST SELLERS FROM AMAZON.COM

Books, C Sharp  Books, .NET  Computers  Electronics  Industrial & Scientific Items  MP3 Downloads  DVD
Camera & Photo  Cell Phones & Services  Magazine Subscriptions  Office Products  On Demand Videos




=============================================================================================== The Slider Control: =================== The WPF controls can be accessed with method cm() using the same code which you have been using to work with Form-based controls. The only difference is in the layout method which is similar to the one class (pasp) uses to mount web controls. One control which has been always neglected is the "Slider Control". It was assumed to be unnecessary, but we need it now since it can help with 3D graphics. The slider control's installation parameters (not including the mounting parameters which have already been discussed) are: cis : The control's label. Will be discussed in details next. lf,of : Width or Height of the control. This also sets the orientation of your wanted slider control. If you want a horizontal one, specify (lf) and keep (of=0) If you want a vertical one, specify (of) and keep (lf=0) js : Minimum and Maximum values. They are the two values you receive from the slider control when it's at its two extreme positions. cus : Contains the initial value where you like the pointer to start at. Handling the Slider Control's event: ------------------------------------ Each time the slider control is activated, method update() is called with the slider's keyname and the value which its pointer is at assigned to (od) Control's Labels: ================= We normally like to place a label near any control in order to identify it. For this reason, PC# allows you to specify a label to almost all controls. You assign the label to (cis) and assign to (os) a direction code which can be (n/s/e/w) which determines where the label should be relative to the control. The positions are as follows: n: (Default) Place label above control. s: Place label under control. e: Place label to the right of control. w: Place label to the left of control. Labels are placed very close to their controls. You can seperate them from their controls by any distance by adding spaces or line feeds before or after the label's text depending on the direction code which you have specified. Here are two examples: cis="Label\n";os="n"; // Place the label above control seperating the two with a linefeed. cis=" Label"; os="e"; // Place the label right of control seperating the two with space. In class (pasp), labels have been doing great jobs. HTML has been possible to use with them so we have been able to use them to add several lines of text, tables, hyperlinks with variety of colors and fonts. Here we don't have all this luxury, but we can still insert linefeeds into a label's text to make it a multi-line one as we'll do with the slider's label in the next example. The Labels are displayed using the same font which is assigned to the control and the color which is assigned to the control's foreground. Using WPF 2D Graphics: ====================== Just like we made method cm() usable without changes for the WPF, we like to make method gm() also usable with minimum changes. We already know that we can import version 2 graphics to our WPF classes, but it should be better if we can use the WPF itself to do the job. In fact, if you intend to place your WPF classes on the web, you can't use class (pcs) To receive version 2 graphics, we used an Image control, we'll do the same with the WPF 2D graphics. This requires setting the graphical output device to the Image control which you like to draw into. You do that by assigning the keyname of the control to (cs) and calling gm("sdi") When your drawing is complete, you call gm("fdi") which means "Finish drawing to the image control device". Whatever you draw will not show up until this method is called. Method gm()'s new parameters: ----------------------------- The WPF does not use type "float" which has been used with version 2 graphics, it uses type double instead. Therefore, we have also switched method gm()'s input parameters to their equivalent type double ones. This means that: jd,kd replace jf,kf id,od replace lf,of Some of the values required but not extensively used, have been assigned to variables of type "double" in Version 2. As an example, (jd,kd), (id,od) have been used to supply scaling and shearing factors when setting up an Affine Transform object. Those valuse are now assigned to (jf,kf), (lf,of) instead. In other words, when we use the WPF for drawing, we use an opposite logic in selecting variable types. ============================================================================================= Example 2: Create a slider control which changes values in the range (+5:-5) Set its initial value at zero. Create a text field and make it constantly show the value which the slider's pointer is at. Also create an Image control and use it to display an image and several shapes. Show how to fill a shape with a texture brush also. ============================================================================================= //assembly ms1.exe; public class a : ms1 { // using pcs3 public override void init() { base.init(); } public override void setup() { PageNumber=2;base.setup(); // Execute master class's setup() supplying it with page no. //----------------------------------- gr3 Contents ----------------------------------- cns="gr3"; // gr3 is divided into 2 col's. cs="gr4";cis="g1";j=0;oxd=0.5;ds="w";cls="S9y7";fns="tr12";cm("i"); cs="gr5";j=1;k=0;oxd=0.5;ds="e";cls="S9y7";fns="crb10";cm("i"); //----------------------------------- gr4 Contents ----------------------------------- cns="gr4"; // gr4 is divided into 2 rows. cs="tf0";cis="Display";os="s";k=0;ds="c";oyd=0.5;lf=60;cus="0.00";cls="b0y0";fns="trb22"; jd=3;cm("i"); // jd=3 means set a 3 pixels border around control. cs="sl0";cis="Slide pointer and watch Display\n -5 0 +5";os="n"; k=1;oyd=0.5;js="-5,5";cus="0";lf=200;ds="c";cls="S9b2";fns="crb12";cm("i"); //----------------------------------- gr5 Contents ----------------------------------- cns="gr5"; // gr5 is not divided. cs="im1";cis="\n2D Drawings";os="s";ds="c";ims="";lf=200;of=200;fns="trb16";cm("i"); } //------------------------------- Handling slider events ------------------------------ public override void update() { if ("sl0".Equals(cs)) { // If Slider "sl0" has generated this event ib=true;om("fd"); // Convert (od) to string reducing decimal digits to two. cus=os;cs="tf0";cm("su"); // and set it into text field control. } } //----------------------------- Drawing into Image control ---------------------------- public override void run() { cs="im1";gm("sdi"); // Make Image Control "im1" the graphical output device. kd=-35;id=od=80;fls="images\\flower.jpg";gm("cid"); // Display an image 35 pixels under center. fls="images\\flower.jpg";gm("blf");gm("spt"); // Create a new texture brush using the same image. kd=30;id=3;od=90;gm("c=f"); // Create equally sided triangle and fill it with the brush // Place it 30 pixels above center. cls="y0";id=3;gm("sps"); // Create a 3 pixels wide pen of yellow color. id=6;od=100;gm("c=d"); // Create Hexagon and draw it at center. cls="r0";id=1;gm("sps"); // Create a new pen/brush of solid red color. id=od=150;gm("crd"); // Create a new Rectangle and draw it at center. cls="b0";id=1;gm("sps"); // Create a new pen/brush of solid blue color. id=od=150;gm("ced"); // Create a circle and draw it at center. gm("fdi"); // Finish drawing into the specified Image control. } } ==============================================================================================


=============================================================================================== Are we really drawing in pixels? ================================ No. We are just pretending we are! All drawings are relative, but we are trying to make our drawings compatible with class (pcs)'s drawings. We try to think in pixels, just like we used to do with class (pcs) Some people like to use small numbers like 1 or 2 for the widths and heights of the objects they draw. This is not very good since it teachs us to neglect accuracy and also because the default width of a pen is still one (it used to be one pixel in class pcs) However, the variable which you assign the pen's width to when you create a pen is now (id) which is of type double, so it can be assigned a fraction. More about the WPF 2D Graphics: =============================== There is almost no difference between the PC# methods which operates on Version 2 graphics and the ones which operate on WPF 2D graphics other than the types of used variables. Drawing lines, Shapes, images and text: --------------------------------------- jd,kd : Location of object's center relative to graphical output device's center. id,od : Width and height of shape. lf,of : Shear factors if necessary ad : Rotation angle in degrees if necessary. For lines, (jd,kd) are coord's of start point and (id,od) are coordinates of end point. For text, (jd,kd) represent location of text center. Font code (fns) and text to draw (os) are also required. For images, you need to supply their center location in (jd,kd) and their desired width and height assigned to (id,od) in addition to the file name or URL assigned to (fls) All modes are the same. Affine Transform: ----------------- jd,kd : Present location of object's center relative to graphical output device's center. jf,kf : Scale factors. lf,of : Shear factors. id,od : Translation. Required displacement of object. ad : Rotation angel. You set the unit transform by calling gm("stu") To apply it to a shape create the shape without drawing then call gm("gtd") to draw it or gm("gtf") to fill it after being transformed. As explained before, we use the transformation order: Scale - Shear - Rotate - Translate. So, you must plan all your object transformations accordingly. Note that the first 3 operations are performed around object's center without changing the center's location. 3D Effects: ----------- Both the "Reflection" and "Depth" 3D effects are available without changes other than variable types which are: REFLECTION: jd,kd: Desired location of object center relative to Graphical device's center cls : Wanted base color of : Brightness factor. DEPTH : id : Depth. ad : 3D inclination angle relative to negative X-axis. cls : Combined code of brightest-Darkest colors. Shapes must be created at CENTER prior to applying 3D effects to them. ============================================================================================== Example 3: Rewrite examples 7 and 8 of the "Drawing" chapter to get them to run using the Windows Presentation Foundation (WPF) software. ============================================================================================== //assembly ms1.exe; public class a : ms1 { // using pcs3 // Make sure to keep the commented word "pcs3" public override void init() { base.init(); } public override void setup() { PageNumber=3;base.setup(); // Execute master class's setup() supplying it with page no. //----------------------------------- gr3 Contents ----------------------------------- cns="gr3"; // gr3 is divided into 2 col's. cs="gr4";cis="g1";j=0;oxd=0.5;ds="w";cls="S9y7";fns="tr12";cm("i"); cs="gr5";j=1;k=0;oxd=0.5;ds="e";cls="S9y7";fns="crb10";cm("i"); //----------------------------------- gr4 Contents ----------------------------------- cns="gr4"; // gr4 is not divided. cs="im1";cis="\n3D Effects, Reflection";os="s";ds="c";ims="";lf=200;of=200;fns="trb16";cm("i"); //----------------------------------- gr5 Contents ----------------------------------- cns="gr5"; // gr5 is not divided. cs="im2";cis="\n3D Effects, Depth";os="s";ds="c";ims="";lf=200;of=200;fns="trb16";cm("i"); } public override void run() { //-------------------------------- Drawing the Jewel ------------------------------------ cs="im1";gm("sdi"); // Set (im1) as graphical output device. cls="y0";gm("sps"); // Create yello brush id=od=195;gm("crf"); // and paint background with it. //-------------------------------- Drawing the object ----------------------------------- id=od=170;gm("ce"); // Create the circular gold plate cls="o5y5";gm("spl"); // Prepare linear gradient brush for it gm("grf"); // then render-fill the gold plate. id=6;od=50;gm("c="); // Create hexagon shape object at center. of=1;cls="r0";ks="r";gm("grs"); // Draw the object using sp effects-refl at of=1;jd=45;cls="b0";ks="r";gm("grs"); // center in red, then repeat 6 times using of=1;jd=-45;cls="b0";ks="r";gm("grs"); // different colors and different locations of=1;jd=22;kd=40;cls="g0";ks="r";gm("grs"); of=1;jd=-22;kd=40;cls="m0";ks="r";gm("grs"); of=1;jd=22;kd=-40;cls="m0";ks="r";gm("grs"); of=1;jd=-22;kd=-40;cls="g0";ks="r";gm("grs"); id=od=25;gm("ce"); // Create a circle at center (pearl) for (int x=0;x<20;x++) { // Draw it 20 times using sp effects-reflection jd=80;kd=18*x;kb=true; // at locations around the plate. Polar coord's of=1;cls="p0";ks="r";gm("grs"); // are used for specifying locations } gm("fdi"); // Finish drawing to (im1) //-------------------------------- Drawing the 3D Text --------------------------------- cs="im2";gm("sdi"); // Set (im2) as graphical output device. cls="b0";gm("sps"); // Create blue brush id=od=195;gm("crf"); // and paint background with it. os="PC#";fns="trb100";gm("ct"); // Create text geometry. ks="d";ad=30;id=10;cls="s9s0";gm("grs"); // Draw text using 3D effects-depth gm("fdi"); // Finish drawing to (im2) } } ==============================================================================================


=============================================================================================== PLAYING VIDEO ============= The new method vm(): ==================== Method gm() of class (pcs3) which has been written initially for classes (pcs) and (pasp) has been modified to fit the WPF 2D Graphics and will be used for this purpose. The new method vm() will handle the new features of the WPF like video and 3D Drawing. Playing video files: ==================== The image control which has proven to be a useful graphical output device which can display all shapes and images can also show movies. So, to play a movie, you need to create an image control and call method gm("sdi") with its keyname to start and to call gm("fdi") to finish at the end. After setting the graphical output device, you call vm("mvo") to open a new video play operation, then you load the movie file by supplying its URL or its local file path (assigned to fls) to method vm("mvl") You can then call vm("mvp") to play the movie and call vm("mvc") to close and execute the video play operation. Here are the most useful video modes: mvo : Open a new video play operation. IN: id,od (optional) width,height of movie display rectangle. mvl : Load video file/URL (assigned to fls) mvp : Play mvu : Pause mvs : Stop mvv : Set volume. IN: id=wanted volume (range is 0:1) mvb : Set Balance. IN: id=wanted balance (range is -1:1) mvc : Execute and Close current video play operation. =========================================================================================== Example 4: Show how to play a video file and how to set the play volume and balance. Show also how to stop it and pause it. =========================================================================================== We used the video file "bear.wmv" which is a short movie file sample that comes with Windows Vista. You need to search for it into your computer or search for any file with same extension, then to copy the file to your working directory before running this example. If you'll be using a different file, modify the line marked with **** with the new file name. ------------------------------------------------------------------------------------------- //assembly ms1.exe; public class a : ms1 { // using pcs3 public override void init() { base.init(); } public override void setup() { PageNumber=4;base.setup(); // Execute master class's setup() supplying it with page no. //----------------------------------- gr3 Contents ----------------------------------- cns="gr3"; // gr3 is divided into 2 col's. cs="gr4";cis="g1";j=0;oxd=0.5;ds="w";cls="S9y7";fns="tr12";cm("i"); cs="gr5";j=1;k=0;oxd=0.5;ds="e";cls="S9y7";fns="crb10";cm("i"); //----------------------------------- gr4 Contents ----------------------------------- cns="gr4"; // gr4 is divided into 3 col's and 3 rows. cs="sl0";cis="Volume Control\n0 5 10";os="n";k=0;i=3;oyd=0.33; js="0,10";cus="5";lf=232;ds="c";cls="S9b2";fns="crb12";cm("i"); cs="sl1";cis="Balance Control\nL 0 R";os="n";k=1;i=3;oyd=0.33; js="-5,5";cus="0";lf=232;ds="c";cls="S9b2";fns="crb12";cm("i"); cs="bt0";cis="Play";j=0;k=2;ds="c";oxd=0.33;oyd=0.34;cls="s9G1";fns="trb22";jd=3;cm("i"); cs="bt1";cis="Pause";j=1;k=2;ds="c";oxd=0.33;oyd=0.34;cls="s9Y1";fns="trb22";jd=3;cm("i"); cs="bt2";cis="Stop";j=2;k=2;ds="c";oxd=0.34;oyd=0.34;cls="s9r0";fns="trb22";jd=3;cm("i"); //----------------------------------- gr5 Contents ----------------------------------- cns="gr5"; // gr5 is not divided. cs="im1";cis="\nVideo";os="s";ds="c";ims="";lf=200;of=200;fns="trb16";cm("i"); } public override void update() { if ("sl0".Equals(cs)) { // If volume control activated: id=od/10;vm("mvv"); // Adjust value to be (0:1) then set volume } else if ("sl1".Equals(cs)) { // If balance control activated: id=od/5;vm("mvb"); // Adjust value to be (-1:1) then set balance } else if ("bt0".Equals(cs)) { // If Play button clicked: vm("mvp"); // Play movie. } else if ("bt1".Equals(cs)) { // If Pause button clicked: vm("mvu"); // Pause play. } else if ("bt2".Equals(cs)) { // If Stop button clicked: vm("mvs"); // Stop play. } } public override void run() { cs="im1";gm("sdi"); // Set (im1) as graphical output device. vm("mvo"); // Open a new video play operation. fls="bear.wmv";vm("mvl"); // **** Load movie file id=1;vm("mvv"); // Set volume. id=0;vm("mvb"); // Set balance vm("mvc"); // Execute and close video play operation. gm("fdi"); // Finish drawing to (im1) } } ==============================================================================================


============================================================================================== Playing Audio: ============== Method um() contains modes to play audio files of type "wave". This is possible to use in both classes (pcs) and (pcs3) Here is an example which you can try: public override void run() { um("awo"); // Open a new audio-wave file play operation fls="c:\\windows\\media\\chimes.wav";um("awl");// Load audio file. kb=true;um("awp"); // Play file continuously. } New option for drawing with 3D Effects: ======================================= When you use the 3D effects-depth you can select a new style which makes you feel that the drawing grows in size as it moves forward. You can get that style by adding (ib=true) to your parametrs. See next example. New variables which you need to know about: =========================================== As you must know, one of the objectives of Personal C. Sharp is to minimize the number of variables and methods which you use in order to make your job easy and to reduce the chance for errors. However, handling the new 3D classes of the WPF has made it necessary to add two more variables which are (ld) and (dd), both are of type "double". This addition applies to class (pcs3) only. (jd,kd,ld) will be used as the 3D coordinates of a point or a vector. (id,od,dd) will be used as (width,height,depth) of a 3D object. Please make sure not to use those variable names as your local variables. Here is a list of all the variables which have been borrowed from your pre-defined "one char + type" list: cs: Control Keyname. fs: File Keyname. ds: Direction code. ls: Replaces the GUV (is) since (is) is a C# keyword. ad: Angle. ld: 3rd dimension (z) (Class pcs3 only) dd: Depth. (Class pcs3 only) We hope we'll not need more. Please make sure not to use any of these names as local var's. Drawing a Rectangular Block: ============================ If you look at the chapter on "Drawing", you'll see examples which show how to create a Rectangular block by assembling its outer surfaces together and how to draw on those surfaces. You have also seen examples on how to draw cylinders and pyramids of general bases. One objective in developing those drawings is to have 3D objects which can automatically supply the WPF 3D drawing classes with their mesh pattern data. Now it's time to rewrite the methods which create those 3D objects using WPF's software so we can use them. The Rectangular block has been added to the cylinder and pyramid as a 3D object to request. You request drawing a rectangular block by calling gm("cRd") Here are all necessary parameters: jd,kd : location of Rectangular Block's center relative to Form's center. id,od,dd: Width,Height,Depth. cls : Combined color code for "visible lines" and "hidden lines". ib : "Show hidden lines" flag. Hidden lines will be displayed when (ib=true) ============================================================================================== Example 5: Show how to use the new 3D effects feature. Also show how to draw a rectangular block of dimensions 40 X 80 X 50. Make hidden lines appear. ============================================================================================== //assembly ms1.exe; public class a : ms1 { // using pcs3 // Make sure to keep the commented word "pcs3" public override void init() { base.init(); } public override void setup() { PageNumber=5;base.setup(); // Execute master class's setup() supplying it with page no. //----------------------------------- gr3 Contents ----------------------------------- cns="gr3"; // gr3 is divided into 2 col's. cs="gr4";cis="g1";j=0;oxd=0.5;ds="w";cls="S9y7";fns="tr12";cm("i"); cs="gr5";j=1;k=0;oxd=0.5;ds="e";cls="S9y7";fns="crb10";cm("i"); //----------------------------------- gr4 Contents ----------------------------------- cns="gr4"; // gr4 is not divided. cs="im1";cis="\n3D Effects, Depth";os="s";ds="c";ims="";lf=250;of=250;fns="trb16";cm("i"); //----------------------------------- gr5 Contents ----------------------------------- cns="gr5"; // gr5 is not divided. cs="im2";cis="\nRectangular Block";os="s";ds="c";ims="";lf=250;of=250;fns="trb16";cm("i"); } public override void run() { //------------------------------- 3D Effecte - Depth ---------------------------------- cs="im1";gm("sdi"); // Set (im1) as graphical output device. cls="b6";gm("sps"); // Create light blue brush id=od=250;gm("crf"); // Paint background with it. jd=20;kd=-30;os="PC#";fns="trb80";gm("ct"); // Create text geometry. ks="d";ad=30;id=100;ib=true;cls="s9s0";gm("grs"); // Draw text using 3D effects-depth with scaling gm("fdi"); // Finish drawing to (im1) //--------------------------- Drawing the Rectangular Block --------------------------- cs="im2";gm("sdi"); // Set (im2) as graphical output device. cls="b6";gm("sps"); // Create light blue brush id=od=250;gm("crf"); // Paint background with it. id=40;od=80;dd=50;ib=true;cls="S9s0";gm("cRd"); // Create 40X80X50 Rect Block, show hidden lines cns="yz-20"; // Container: Parallel to yz plane at x=-20 cls="r0";gm("sps"); // Create red pen fns="trb20";os="PC#";gm("ctf"); // Draw the string on that plane. gm("fdi"); // Finish drawing to (im2) } } ==============================================================================================


=============================================================================================== 3-D DRAWING using the WPF Level I ========================= (Requires .NET v3.5 and PC# v3.0) The New WPF 3D Module: ===================== What makes the new 3D module of the WPF interesting is the following new features: (1) It allows viewing the 3D object from any direction and at any distance. What you see on the screen is actually the picture which a camera picks up. the type, position and direction of that camera are settable. (2) The color and shades which you see depend on the lights around the object. You can choose from a variety of light types placed at whatever positions you like. (3) The color which the object appears at depends also on the type of material it's made of, how reflective it is to light in general and to each light color in particular. Data required by the WPF 3D module: ================================== The WPF 3D module can help you viewing a 3D object under variety of conditions, transforming the object and animating it if you like, but it does not help you in creating the object. It requires that you supply it with data regarding an object which you know to start with. This data includes the 3D location of (at least) each vertex of the object and a mesh pattern data. 1 0 +----------------+ | /| | / | | / | | / | | / | | / | | / | | / | | / | | / | | / | | / | | / | | / | | / | |/ | +----------------+ 2 3 If the object was a rectangle like this one, the data required would be the 3D coordinates of the 4 points (0,1,2,3) and an index array which can be (0,1,2,0,2,3) what these 6 numbers mean is that the object is made of 2 triangles, if we list the points which make each triangle moving counter-clockwise, the two lists would be (0,1,2) and (0,2,3) This seems to be easy when it is in 2D plane. If the rectangle, has been in 3D space making a different angles with each of the three 3D planes, things could have been harder. If it was a more complicated shape, the difficulty could have been higher. We have developed a software which allows drawing rectangular blocks, cyliders and pyramids with general bases. They can be drawn using class (pcs)'s graphics module and can also be drawn using the WPF's one. Additionally they can automatically supply the WPF 3D module with their points and triangle indices data (the mesh pattern) Personal C Sharp simplification: ================================ The most difficult part is the mesh pattern data described above which is now "no work" if you limit your 3D objects to Rectangular blocks, cylinders and pyramids which we know that you can't do. Fortunately, this difficulty is limited to Level I and will be eliminated when you reach Level II. The data is supplied to PC# software in the form of 4 arrays as follows: PXD[] An array of type "double" which contains the X component of each point's coordinates. PYD[] An array of type "double" which contains the Y component of each point's coordinates. PZD[] An array of type "double" which contains the Z component of each point's coordinates. IX[] An array of type "int" which contains the indices of the points of all triangles which make the shape in the order described above. If you like to use one of our 3D objects, for example a pyramid with hexagonal base sitting on a plane which is parallel to the YZ plane with enclosing circle diameter of 100 and a height of 150, you would use the code: id=6;od=100;dd=150;js="yz";gm("cPv"); This will create the required 4 arrays for you. The last char in the mode string 'v' means create vertex arrays only (Don't draw or fill the generated object) If you are wondering how large these arrays are, in the next example we'll create the vertex arrays of a hexagonal cylinder, circular cylinder and a pyramid with a 10 sides base. The total of all numbers to be supplied exceeds 1,000. The PC# defaults: ----------------- The basic 3 setups which you need to do after supplying the "mesh" data are "lights setup", "object's color and material setup" and "camera setup". We are not going to get into details regarding them now. However the default settings which PC# will set for you if you don't supply data for the 3 items are: (1) A combination of 3 lights will be available. One directional light at the top of the object, one directional light coming from the upper, left corner (at z=maximum) direction toward the center and one ambient light. (2) A perspective camera sitting at the upper, right (at z=maximum) corner and directed toward the center where the object is expected to be. The camera has a field of view of 60 degrees. (3) The object is assumed to be made of light diffusing material and colored with our default brush which is black for the foreground and white for the background. How to draw 3D objects: ----------------------- (1) Call method gm("cRv"), gm("cCv") or gm("cPv") to create a rectangular block, a cylinder or a pyramid in order to generate the point arrays PXD[], PYD[], PZD[] and IX[]. If you like to draw a different object, you need to assign data to these arrays by yourself. (2) If you accept all defaults and like the object to be centered into the Graphical Output device, all you need to do is to call vm("cof") to create the object and fill it. If you want to create the object only, call vm("co") Then you can render it later and fill it with vm("grf") or transform it and fill it with vm("gtf") If you don't like the object's center to be at the origin, assign values to (jd, kd and ld) If you have more than one object to draw, repeat the two steps for each and assign different values to (jd,kd,ld) in (2) in order to seperate them. This is just the beginning. There are plenty of items to discuss, but let us have an example before we get further. ============================================================================================== Example 6: Draw a pyramid with 10 sides base which is parallel to the xz plane, a cylinder with circular base which is parallel to the yz plane and a cylinder with hexagonal base which is parallel to the xy plane. Use different color for each. ============================================================================================== //assembly ms1.exe; public class a : ms1 { // using pcs3 // Make sure to keep the commented word "pcs3" public override void init() { base.init(); } public override void setup() { PageNumber=6;base.setup(); // Execute master class's setup() supplying it with page no. //----------------------------------- gr3 Contents ----------------------------------- cns="gr3"; // gr4 is not divided. cs="im1";cis="\n3D Graphics";os="s";ds="c";lf=560;of=250;fns="trb16";cm("i"); } public override void run() { cs="im1";gm("sdi"); // Set (im1) as graphical output device. id=10;od=150;dd=150;js="zx";gm("cPv"); // Create the pyramid with 10 sides cls="S9g4";js="d";vm("cof"); // Use green color for background and // create-fill diffuse material object id=40;od=100;dd=100;js="zy";gm("cCv"); // Repeat with the round (40 sides) base jd=160;kd=30;ld=-50;cls="S9b4";js="d";vm("cof"); // cylinder. use blue color. id=6;od=170;dd=170;js="yx";gm("cCv"); // Repeat with the hex cylinder using jd=-300;kd=-125;ld=50;cls="s9r4";js="d";vm("cof");// red color for background. gm("fdi"); // Finish Image control drawing operation. } } ==============================================================================================


BEST SELLERS FROM AMAZON.COM

Books, C Sharp  Books, .NET  Computers  Electronics  Industrial & Scientific Items  MP3 Downloads  DVD
Camera & Photo  Cell Phones & Services  Magazine Subscriptions  Office Products  On Demand Videos




=============================================================================================== If you don't like the screen shot of last example, don't get disappointed. The poor graphics are caused by sending the images using "jpg" compressed formula through the internet. If you run the code on your computer all colors and shades will look fine. The edge lines of the hexagonal cylinder and pyramid will look more distinctive and the circular cylinder will look smoother. How could edges appear for the hex cylinder and pyramid but not for the circular cylinder? ------------------------------------------------------------------------------------------ We have designed the default light positions and directions so that object edges become distinctive. Despite that the circular cylinder which is actually made of a 40 sides polygon base shows with no recognizable edges. What did we do to make this possible? Each vertex of a cylinder is shared among 3 planes, the base plane and two side planes. If we want the edges to show, we need to list each vertex location in arrays PXD[],PYD[],PZD[] 3 times so that the points which make the triangles of each plane are defined seperately in array IX[]. If we like the side planes to mix making a continuous round surface, we list each vertex twice only. Once for the base and once for the other two planes together. Whenever you create a cylinder or a pyramid with a base which is made of 25 sides or more, we assume that you want a circular object, so we list each vertex twice. Otherwise, we list each vertex 3 times. Why do we need two combined color codes for 3D objects? ------------------------------------------------------- Whenever we use two combined color codes for an object we usually mean that the first one is for the foreground and the second one is for the background. This applies to 3D objects too. However, when we set the color of a 3D object's surface, we are expected to specify the color of the back of that surface too. This color is normally never seen except if the object is only a surface with no volume like a triangle or a rectangle or if the camera is inside the object! We use the foreground color specified in the combined color code to paint the background of that back surface with. We said that if the camera was inside an object which has volume like a cylinder or a cube, it will see everything painted in the color which is set as the color of the back side. How is that possible? You can believe it if you assume that a 3D object is considered to be a hollow shell which is painted inside and outside with different colors. Can we reverse one of the triangles which define an object's surface so it appears in the back surface color? Yes. All we need to do, is to reverse the indices sequence for that triangle in array IX[] so its point listings become in clockwise order instead of counter-clockwise. About the next example: ----------------------- Can we have an example to illustrate that? Yes, in the next example we'll move the camera using a slider control so we can see a triangle and a rectangle at both their front and back sides. We are also going to make the camera penetrate inside a cylinder to look inside it. Additionally we'll modify array IX[] for the rectangle so that the points of one of its composing triangles become listed in a clockwise order causing that triangle to appear in reverse side color. We are going to be using the green color for the outside of all objects and the red color for the back (or the inside) of all objects. The triangle and rectangle are actually a pyramid and a cylinder of a single line base. The line will be vertical alongside the Y axis. We'll then move the triangle along the X-axis to point (-150) and also move the rectangle along the X-axis to point (+150) ============================================================================================== Example 7: Create a triangle at the left, a rectangle at the right and a cylinder at the center paint them all green with reverse side in red. Move the camera using a slider control on a line which is on the xz plane parallel to the x-axis at z=190. The camera will be moving between the two extreme points where (x=-250) and (x=250) Set the z position of the cylinder so that its outer-most point extends in the z direction to the point z=200. This means that when the camera is at its center point it will be inside the cylinder. ============================================================================================== //assembly ms1.exe; public class a : ms1 { // using pcs3 // Make sure to keep the commented word "pcs3" public override void init() { base.init(); } public override void setup() { PageNumber=7;base.setup(); // Execute master class's setup() supplying it with page no. //----------------------------------- gr3 Contents ----------------------------------- cns="gr3"; // gr3 is divided into 2 rows. cs="gr4";k=0;oyd=0.8;ds="n";cls="S9y7";fns="tr12";cm("i"); cs="gr5";j=0;k=1;oyd=0.2;ds="c";cls="S9y7";fns="crb10";cm("i"); //----------------------------------- gr4 Contents ----------------------------------- cns="gr4"; // gr4 is not divided. cs="im1";os="s";ds="c";lf=560;of=250;fns="trb16";cm("i"); //----------------------------------- gr5 Contents ----------------------------------- cns="gr5"; // gr5 is not divided. cs="sl0";cis=" Camera X Position\n-250 -200 -150 -100 "; cis+="-50 0 +50 +100 +150 +200 +250";os="n"; js="-5,5";cus="0";lf=500;ds="c";cls="S9b2";fns="crb12";cm("i"); } public override void update() { if ("sl0".Equals(cs)) { // If Slider "sl0" has generated this event jd=od*50;kd=0;ld=190;vm("scp"); // Apply received value to camera's X postion. } } public override void run() { cs="im1";gm("sdi"); // Set (im1) as the graphical output device. cls="b0";id=2;gm("sps"); id=558;od=235;gm("crd"); id=1;od=150;dd=100;js="xy";gm("cPv"); // Get the vertex data for the triangle jd=-150;cls="r0g0";js="d";vm("cof"); // Draw the triangle at point (-150,0,0) id=40;od=100;dd=200;js="xy";gm("cCv"); // Get the vertex data for the circular cylinder ld=100;cls="r0g0";js="d";vm("cof"); // Draw it at point (0,0,100) id=1;od=150;dd=100;js="yx";gm("cCv"); // Get the vertex data for the rectangle // The 2nd triangle indices occupy the 3 rows (IX[3]:IX[5]) Exchanging values of first // and second rows changes point order from counter-clockwise to clockwise. n=IX[3];IX[3]=IX[4];IX[4]=n; //Exchange contents of IX[3] and IX[4] jd=150;cls="r0g0";js="d";vm("cof"); // Draw rectangle at point (150,0,0) //---- Camera setup ---- os="0,0,190"; // Camera position = Point (0,0,190) js="0,0,-1"; // Look direction = from +ve (Z) to -ve (Z) ks="0,1,0"; // Up Direction = +ve (Y) id=120; // Field of view angle=120 degrees. vm("ccp"); // Create Perspective camera. gm("fdi"); // Finish Image Control drawing operation. } } ---------------------------------------------------------------------------------------------- Notice the following when you run this program: (1) When the camera is at the center, it's inside the cylinder so the entire view becomes red and the rear end of the cylinder becomes visible as a far away circle. (2) When you move the camera to the negative side and start passing the point (-50), you suddenly see the cylinder in green and also the triangle appears in green. The camera is now outside the cylinder. (3) As you continue moving the camera in the negative direction, the green triangle shrinks horizontally, turning into a vertical line and at point (-150) it totally disappears. (4) When you pass (-150) the triangle reappears in red and it keeps growing in size until the camera reachs the end position in the negative direction. (5) If you return to the center then move to point (+50), the cylinder will become green and the rectangle shows up as two triangles, one green and one red. (6) The rectangle keeps shrinking in size to a vertical line and disappear at point (+150) (7) Whe you pass this point, the rectangle starts showing up, but the colors of its 2 triangles become reversed. (8) As you move further in the poitive direction, the rectangle grows in size until the other camera extreme point is reached. ==============================================================================================


=============================================================================================== Material Types: =============== In all the past examples we have been selecting "Diffuse" material for all 3D objects. This has been done by making the assignment (js="d") when creating the objects. Actually, this assignment has not been necessary since it's the default. In general, there are 3 types of material which we can select: d Diffuse Material. This is the default and most common. It means a material which diffuses light like fabrics, wood, regular wall paints,..etc. e Emissive Material. Make this selection when you like the object to shine. s Specular Material. You need to practice with this selection to see if it can be of use to you. It seems that you can't use selection (e) or selection (s) alone. You must use them as top layers with a layer of type (d) underneeth. If you don't do that, material of type (e) appears white regardless to the color which you specify and material of type (s) appears transparent! In the next example, we are going to be creating 3D objects and drawing on them. This makes it perfect for practicing with material type selections. Generalizing the graphical output device: ========================================= The image control has been successfully generalized so that it can now do the following: (1) Draw all 2D Graphics including text. (2) Draw Images. (3) Play movie. (4) Display all the WPF 3D graphics. You can also mix more than one of the drawing tasks above into one image control. You make an image control the graphical output device by assigning its keyname to (cs) and calling gm("sdi") You can then draw any combination of the 4 drawing types listed above, then call gm("fdi") to finish the Image control drawing operation. The 2D drawings will be done first followed with the 3D drawings unless you make the assignment (jb=true) before calling gm("fdi") See remark (2) for more details. The Visual Brush: ================= The second Graphical Output Device after the Image Control is the Visual brush. You set it by calling gm("sdb") then you can draw either geometric shapes and images or 3D objects. When done, you call gm("fdb") to finish the brush drawing operation. After that you can apply the brush to either a 2D or a 3D object's surface to paint it with the drawings. You may repeat the operation more than once to paint the same surface with variety of drawings. REMARKS: ------- (1) Any object which you draw on the visual brush must have a set size which is smaller than or equal to the size of the surface which will receive the drawings. (2) There are two categories of graphics, "2D graphics, images and video" make one category and 3D graphics make another category. The objects used for each of the two categories are not the same. This should not be of concern to you unless drawings from the 2 different categories are going to be covering each other. In this case, you need to specify which one should be on the top. The default is the 3D drawings. If you like a drawing of the first category to be on the top while the image control is the graphical output device, make the assignment (jb=true) before calling gm("fdi) With the Visual Brush, you cannot draw graphics of both categories at the same time. However, you can start a visual brush drawing operation, draw graphics of one category on the brush, finish the operation and paint the target object with the brush, then you can repeat the whole operation to paint the same target again with drawings of different category. Drawing on a 3D object's surface: ================================= In the "Drawing" chapter, you have seen examples on how to draw on 3D planes. Can we do the same using the WPF 3D module. Yes we can. The process is not exactly the same, but the results are the same. In the past examples, you have been drawing each 3D object in two steps: (1) Obtaining the mesh data for an object by using method gm("cRv"), gm("cCv") or gm("cPv) to get the data for a Recatangular block, Cylinder or a Pyramid (respectively) (2) Calling method vm("cof") supplying it with the color assigned to (cls) and the material type code assigned to (js) to create the 3D object. The typical line of code for step (2) has been: cls="r0g0";js="d";vm("cof"); // Draw front surface with green solid brush and back // surface with solid red brush. Use diffuse material. The brush type was not specified since we wanted solid brush which is the default. If we want to specify a different brush, we should assign to (ks) one of the codes "s", "l", "r", "t" or "v" meaning "solid", "linear gradient", "radial gradient", "texture" or "visual" brush. Now, instead of painting the entire object with one solid color we like to paint each surface independantly. The visual brush (described above) is used for the drawing. This means that we need to make the following changes: (1) Instead of drawing the entire object at once we need to draw each surface independantly and assemble them together to make the 3D object. This is not new. We are going to use the same technique which we have used to draw 3D objects using class (pcs) You need to review examples (20,21) of the "Drawing" chapter to know how. To draw a Rectangular block, we are not going to call gm("cRv") any more. We are going to be calling gm("crv") while specifying the container plane and depth assigned to (cns) This will be repeated 3 times, once for each visible side of the rectangular block. (2) We are going to be using the visual brush. So, we are going to set it temporarely as the Graphical Output device, draw on it then assign it to the object by making the assignment (ks="v") when we create the 3D object. (3) The WPF 3D module requires two more arrays of type double to contain the "Texture Coordinates" which are necessary when any brush other than the solid color one is used. This is no work to you. The 2 arrays (TXD[], TYD[]) will be generated automatically with all other mesh data arrays when you call gm("crv") =============================================================================================== Example 8: Draw a 140 X 150 X 100 rectangular block by assembling its three visible sides. Draw the text "PC#" on one side, a Hexagon on another side and an image on the third side. In order to demonstrate our ability to mix different drawings into one image control, start by drawing a frame in 2D space to set the rectangular block into. =============================================================================================== //assembly ms1.exe; public class a : ms1 { // using pcs3 // Make sure to keep the commented word "pcs3" public override void init() { base.init(); } public override void setup() { PageNumber=8;base.setup(); // Execute master class's setup() supplying it with page no. //------------------------------------- gr3 Contents ------------------------------------- cns="gr3"; // gr4 is not divided. cs="im1";cis="\n3D Graphics";os="s";ds="c";lf=560;of=250;fns="trb16";cm("i"); } public override void run() { cs="im1";gm("sdi"); // Set (im1) as the graphical output device. //----------------------------- Drawing a frame in 2D space ----------------------------- cls="g0";id=3;gm("sps"); // Create a 3 pixels wide pen of solid green color. id=247;od=247;gm("crd"); // Create a new Rectangle and draw it at center. //-------------------------------- Drawing the front side ------------------------------- cns="xy50"; // Container: Parallel to xy plane at z=50 (1/2 of depth) id=140;od=150;gm("crv"); // Get vertex data of front rect. js="d";cls="s9r4";ks="s";vm("cof"); // Create-fill the 3D object using solid red brush gm("sdb"); // Set the present visual brush as the gr output device cls="y0";id=1;gm("sps"); // Create solid yellow color brush fns="trb40";os="PC#";gm("ctf"); // Draw the text "PC#" on the Visual brush gm("fdb"); // Finish v brush drawing operation. js="d";cls="s9r4";ks="v";vm("cof"); // Create object in 3D space painting it with visual br //--------------------------------- Drawing the top side -------------------------------- cns="xz75"; // Container: Parallel to xz plane at y=75 id=100;od=140;gm("crv"); // Get vertex data of top rect. js="d";cls="s9b4";vm("cof"); // Create-fill the 3D object using solid blue brush gm("sdb"); // Set the present visual brush as the gr output device cls="s9";id=1;gm("sps"); // Create solid white color brush. id=6;od=80;gm("c=f"); // Draw-fill a hexagon on the visual brush. gm("fdb"); // Finish v brush drawing operation. js="d";cls="s9r4";ks="v";vm("cof"); // Create object in 3D space painting it with visual br //--------------------------------- Drawing the right side ------------------------------ cns="yz70"; // Container: Parallel to yz plane at x=70 id=100;od=150;gm("crv"); // Get vertex data of right side rect. js="d";cls="s9g4";vm("cof"); // Create-fill the 3D object using solid green brush gm("sdb"); // Set the present visual brush as the gr output device fls="images\\flower.jpg"; // Name of Image file to be drawn id=100;od=150;gm("cid"); // Draw image on v brush after scaling it to fit rect gm("fdb"); // Finish v brush drawing operation. js="d";cls="s9r4";ks="v";vm("cof"); // Create object in 3D space painting it with visual br gm("fdi"); // Finish drawing to (im1) } } ---------------------------------------------------------------------------------------------- COMMENTS: --------- (1) When we have been assembling a rectangular block using class (pcs), the depth of the block side which was parallel to plane (yz) has been negative, but here it's postive. This is because with class (pcs), we have been drawing the left side, but here we are drawing the right side of the rectangular block. (2) In this example We have drawn the visible sides of the 3D object only. In general, the right thing to do is to draw all 6 sides. If we have been doing transformation or animation, the object's back side could have appeared. (3) When we talk about the front and back sides of the object, we must keep in mind that the object center coincides with the graphical output device's center. All vertex data are based on that. This means that if the side you have requested to draw was parallel to the xy plane with a negative depth (z<0), the side you get will be a back side, painted with back side color and anything you draw on it will not be visible unless you move the camera to view the back side. ==============================================================================================


=============================================================================================== Drawing a large number of 3D objects into one page: =================================================== There are more than one way to do so. You may create a large number of grids, one for each item and create image controls into each. Each image control can display one item. You can also use the method which we have used in example 6 in which we have created only one image control and set the 3D coordinates of each item using (jd,kd,ld) to seperate them. The first method requires plenty of code and the second one is hard to do. Using the visual brush as a graphical output device can be the best choice. It can allow us to position the items easily in 2D space and the entire job can be done in a loop which requires minimum code. ============================================================================================== Example 9: Draw 9 cylinders with variety of sides into one page. The sides should be in the range (3:11) Draw a frame around each item and display a description label within the frame. Also display a title for the page. ============================================================================================== //assembly ms1.exe; public class a : ms1 { // using pcs3 // Make sure to keep the commented word "pcs3" public override void init() { base.init(); } public override void setup() { PageNumber=9;PageHeight=630;base.setup(); // Execute master class's setup() supplying it // with page no. and height. //------------------------------------- gr3 Contents ------------------------------------- cns="gr3"; // gr3 is not divided. cs="im1";cis="3D Graphics";os="s";ds="c";lf=560;of=620;fns="trb16";cm("i"); } public override void run() { cs="im1";gm("sdi"); // Set (im1) as the graphical output device. cls="y7";gm("sps"); // Create a new pen/brush of background color. kd=305;id=557;od=50;gm("crf"); // Create a new Rectangle to house title. cls="r0";id=3;gm("sps"); // Create a new pen/brush of solid red color. kd=300;os="CYLINDERS";fns="trb20";gm("ctf");// Display title for (int n=0;n<9;n++) { // Repeat the following 9 times: cls="S9";id=2;gm("sps");fns="trb12"; // Set color & font for frame and item lables. jd=185*(n%3)-185;kd=-185*(int)(n/3)+105; // Set position of each item's label. os="Number of sides="+(n+3);gm("ctf"); // Display label. jd=185*(n%3)-185;kd=-185*(int)(n/3)+185; // Set position of each square's center point id=od=180;gm("crd"); // Draw square. gm("sdb"); // Set visual brush as graphical output device. id=n+3;od=100;dd=100;js="yz";gm("cCv"); // Get vertex data for each cylinder. cls="r0b4";js="d";vm("cof"); // Create 3D object and display it in blue color. gm("fdb"); // Finish drawing to brush gm("grf"); // Paint the square with the visual brush. } gm("fdi"); // Finish drawing to (im1) } } ---------------------------------------------------------------------------------------------- Everything seems to be fine except that the graphics quality of the WPF 3D module is not as high as we like it to be. As you can see, outer edges of all 3D objects are rough. This problem becomes more noticeable when the objects are small in size. Notice the scrollbars which automatically show up when we set the page height or page width to values which are beyond what the window can display without the bars. ==============================================================================================


=============================================================================================== Operating on PC# internal 3D objects and arrays: ================================================ Some of the objects and arrays which are used by PC# to access the WPF classes are declared public in order to allow you to operate on them whenever you find it necessary. Here is a list of them: igp = Image control which is currently the Graphical output device. vbp = Visual Brush which is currently the Graphical output device. gmp = Last GeometryModel3D object created. gmo = Last 2D Geometry object created. pcp = Present PerspectiveCamera ocp = Present OrthographicCamera mcp = Present MatrixCamera alp = Present AmbientLight dlp = Present DirectionalLight plp = Present PointLight Mesh data: ---------- PXD[],PYD[],PZD[] Array of type "double" which contain the X,y & z coordinates of each point of the 3D object. NXD[],NYD[],NZD[] Arrays of type "double" which contains the Vector3D components of the Normal property of each point. IX[] An array of type "int" which contains the indices of the points of all triangles which make the shape in an order which we have discussed before. TXD[],TYD[] Arrays of type "double" which contains Texture X & Y Coordinates. REMARKS: -------- (1) Whenever you supply the vertex data for a 3D object, you may like to include point normals with your data. The Normal of a point on a 3D object is the vector which is perpendicular to the surface at that point and points to outside the object. Before you supply this data, you should create the type double arrays NXD[], NYD[] and NZD[] which are defined by class pcs3 as arrays of the same lengths as arrays PXD[], PYD[] and PZD[]. Then you should load them with the (x,y & z) components of each vector which represents the normal at each point in the point arrays at the same order. PC# does not use the Normal arrays when it supplies data for a Rectangular Block, a Cylinder or a Pyramid. It uses a different method which has been explained before. (2) When you supply your own vertex data for an object, remember not to make the mistake of redeclaring the vertex arrays. We mean by that: DO : IX=new int[50]; DO NOT: int[] IX=new int[50]; since obviously array IX[] of the second line is not the one which class (pcs3) can use. (3) You can get all the references listed above for public objects by calling vm("O") with no parameters, except the Light objects which require supplying the method with their keynames. Comparing class (pcs) with class (pcs3): ======================================== Working with the WPF graphics is made to be very similar to working with class pcs's graphics. With class pcs, all shapes are represented by one object of type GraphicsPath which is (gpp) Similarly, with class pcs3, all 2D shapes are represented by one object of type Geometry which is (gmo) and all 3D shapes are represented by one object of type GeometryModel3D which is (gmp) With class pcs, you can create a shape by calling method gm("cx"), gm("cxd") or gm("cxf) where x is a character which represents the type of shape wanted. It can be (r,e,=,p,i,t,R,C,P) meaning (Rect, ellipse, equally sided object, general path, image, text, Rectangular Block, Cylinder or Pyramid) respectively. If the mode string ends with "d", the object's outlines are drawn to the graphical output device using the present Pen object. If the mode string ends with "f", the object is filled with the present brush. If the third character was omitted, the object will be created only without display. Class pcs3 functions identically regarding 2D graphics. With 3D graphics it can either create objects only with vm("co") or create and fill them with vm("cof") It cannot draw outlines. With class pcs, you can work on the shape object after being created and (gpp) become its reference. Calling gm("grd") or gm("grf") draws or fills the object. Methods gm("gt"), gm("gtd") and gm("gtf") applies present unit transform (utp) to the object then it can either draw its outlines or fill it depending on the 3rd character of the mode string. With class pcs3, you can also work on the shape object after being created and (gmo) or (gmp) become a reference of its underlaying Geometry. The same modes of method gm() are available when working with 2D objects. With 3D objects, methods vm("grf"), vm("gt") and vm("gtf") are available. 3D TRANSFORMS: ============== The transformation technique which we have used with 2D graphics has made transformation very easy and more importantly error free. So, we are going to do the same with 3D transformation. To remind you with it, you need to plan your transformation job as follows (in the same order): (1) If you need to scale the object, assign the (x,y and z) scale factors to (js) seperated with commas. Remember that the object will be scaled up or down while its center remains at same position. (2) If you need to rotate the object, assign the rotation axis' 3D vector components to (ks) seperated with commas and the rotation angle in degrees to (ad) (3) If you like to move object's center in all 3 directions by the amounts (x1,y1,z1), assign these 3 values to (os) seperated with commas. (4) Call vm("st") to set the transform. (5) After that, you can transform (gmp) at any time by calling vm("gt") or you can transform it and draw it at the same time by gm("gtf") All this should be preceded with vm("co") in order to create (gmp) for your 3D object. As you must have noticed, we have not included "shearing" in the process. We may do that at a later time. ============================================================================================== Example 10: Create a circular cylinder and draw it. Scale the cylinder to half in all three directions and draw it again. Rotate it by 90 degrees around Z-axis and draw it for the third time. ============================================================================================== //assembly ms1.exe; public class a : ms1 { // using pcs3 // Make sure to keep the commented word "pcs3" public override void init() { base.init(); } public override void setup() { PageNumber=10;base.setup(); // Execute master class's setup() supplying it with page no. //----------------------------------- gr3 Contents ----------------------------------- cns="gr3"; // gr3 is not divided. cs="im1";cis="\n3D TRANSFORMS";os="s";ds="c";lf=560;of=250;fns="trb16";cm("i"); } public override void run() { cs="im1";gm("sdi"); // Set (im1) as graphical output device. id=40;od=100;dd=100;js="zy";gm("cCv"); // Obtain vertex data for a cylinder. //---------------------------------- Original Object ------------------------------------ cls="S9";gm("sps"); // Create black pen. jd=-95;kd=-165;id=od=180; // Position for first text line os="Original";gm("ctf"); // Draw the text. jd=-185;id=od=180;gm("crd"); // Draw the containing square. gm("sdb"); // Set visual brush as graphical output device. cls="S9b5";js="d";vm("cof"); // Create and draw-fill original object in blue. gm("fdb"); // Finish with brush as graphical out device. gm("grf"); // Paint first square with visual brush. //--------------------------------- Scaled down Object ---------------------------------- cls="S9";gm("sps"); // Recreate black pen. jd=90;kd=-165;id=od=180; // Position for second text line os="Scaled to half";gm("ctf"); // Draw text. id=od=180;gm("crd"); // Draw containing square. gm("sdb"); // Set visual brush as graphical output device. cls="S9g5";js="d";vm("co"); // Recreate original object in green w/o drawing. js="0.5,0.5,0.5";vm("st"); // Set transform to scale object by 0.5 vm("gtf"); // Transform and draw-fill object gm("fdb"); // Finish with brush as graphical out device. gm("grf"); // Paint second square with visual brush //----------------------------------- Rotated Object ------------------------------------ cls="S9";gm("sps"); // Recreate black pen. jd=280;kd=-165;id=od=180; // Position for third text line os="Rotated 90 degrees";gm("ctf"); // Draw text. jd=185;id=od=180;gm("crd"); // Draw containing square. gm("sdb"); // Set visual brush as graphical output device. cls="S9r5";js="d";vm("co"); // Recreate original object in red w/o drawing. ks="0,0,1";ad=90;;vm("st"); // Set transform to rotate obj 90 degrees around vm("gtf"); // Z-axis. Transform and draw-fill object. gm("fdb"); // Finish with brush as graphical out device. gm("grf"); // Paint third square with visual brush. gm("fdi"); // Finish Image control drawing operation. } } ---------------------------------------------------------------------------------------------- COMPILING: Use tool "pcp" or "pcpr" as usual. Make sure to keep the commented statement "//assembly ms1.exe;" at the top and also to keep the commented word "pcs3" at the class declaration line since both are required by the compiling tools. For more details read the text titled "Compiling" which follows example 1. COMMENTS: --------- Since you already know about objects involved, we can explain this example more technically. (1) We called method gm("cCv") to create the necessary arrays once only at the top. This is because these arrays do not get erased until you request the vertex data of a new object by calling gm("cxv") where x can be "R", "C", "P", "r" or "=". In this example, we needed the vertex data for one object only. (2) Why have we been drawing the label which goes with each square before drawing the square itself? When the label text was drawn the present 2D object (gmo) has been created as the text's geometry object. When the square was drawn, (gmo) has been overwritten to become the square's geometry object. Immediately after (gmo) became the square's object, we set the visual brush as the graphical output device, drew on it, then painted (gmo) with it. This is why the last (gmo) which was available immediately before using the brush must be for the square. (3) The same idea applies to 3D. Each time we call vm("co") to create a 3D object, (gmp) is recreated to point to that object. So, when we set the transform then call vm("gtf"), we know that we are applying the transform to last (gmp) which means to the last created 3D object. (4) Here is one question which you may like to ask "Both (igp) and (vbp) accept 2D and 3D drawings. If we have drawn 2D figures on the visual brush the 2D Geometry object (gmo) could have changed. So how could we guarantee that the geometry object which has been painted with the visual brush at the end belongs to the square? The answer is that when you call gm("sdb") to make (vbp) the graphical output device, the first thing method gm() does is creating a second reference to both (gmo) and (gmp) to persist the two objects, and when you call gm ("fdb") to finish the brush drawing operation, the original values of (gmo) and (gmp) are restored. ==============================================================================================


=============================================================================================== Camera and Lights ================= The first time we introduced a short course in mathematics was in the chapter of "Imaging" when we discussed Matrices. The WPF contains classes which include methods which perform Vectors and Quaternions mathematical operations in addition to 3D Matrices. However, writing WPF application software requires only a small knowledge of them. This is what we are going to start with here. We may get into more details later if we find that necessary. VECTORS: ======== A vector is an amount which has a magnitude and direction but it does not have a specific location. This means that all vectors in a 3D space which have same magnitude and parallel to each others are the same. And since they are the same, we can simplify defining each group of equal vectors by using the one of the group which starts at the origin and ends at a point in the 3D space. A vector is usually represented with an arrow of the same length as the vector's magnitude and pointing to the same direction as the vector's direction. If the tail of that arrow starts at the origin and the tip ends at point (x,y,z), we call that vector(x,y,z) Normalized Vectors (or unit vectors): ------------------------------------- Vectors are used in the WPF 3D module to represent items which have magnitude and direction like "directional lights" and also items which have direction only like "Camera Up direction". Vectors which represent direction only have a magnitude of 1. They are called unit vectors or normalized vectors. You can normalize a vector be dividing it by its magnitude. The magnitude of vector (x,y,z) is (x^2 + y^2 + z^2)^0.5 [We mean by this the square root of (x square + y square + z square)] The X, Y and Z axes are normalized vectors. Their values are (1,0,0), (0,1,0) and (0,0,1) respectively. Normally, you don't have to normalize vectors which mean "Direction" to the WPF since the WPF will do this job for you. COMPLEX NUMBERS: ================ The complex number (n), in general can be represented by two components, real component and imaginary one as follows: n = a + bi where i=(-1)^0.5 Mathematicians have found that representing a point in 2D space with a complex number could simplify some calculations especially "rotation". This, of course is in addition to many other applications in physics and other siences which have been simplified with the use of complex numbers. In 2D space, we use the real part of the number (a) to represent the (x) value of the point and the imaginary part (b) to represent the (y) value. QUATERNIONS: ============ If the real and imaginary parts of a complex number can represent a point in 2D space, how can we represent a point in 3D space? the answer is by using 4 components. One real and 3 imaginary components. The Quaternion can be expressed as follows: q = w + xi + yj + zk Quaternions are used in the WPF for rotation transformation. We see no need for more about them at this point. CAMERA TYPES: ============= There are three types of cameras: Perspective, Orthographic and Matrix. (1) The Perspective Camera: --------------------------- The Perspective camera is the standard camera which everybody uses. It makes the nearby sides of the object appear to be larger than the far sides which is what everybody expects. To create a perspective camera, call vm("ccp") with the following parameters: os : Camera position. Assign the (x,y,z) coordinates of the camera position to (os) seperated with commas. When the camera is far away from the object, you expect the object to appear smaller. js : Look Direction. Assign the x,y,z components of the "Look" direction vector to (js) seperated with commas. Normally, you set the object at the center. So, if you position the camera at point (x,y,z) you like to make your look direction vector (-x,-y,-z) ks : Up Direction. Assign the x,y,z components of the camera's upward direction vector to (ks) seperated with commas. Normally we like that direction to be the positive Y-axis. So we make the assignment: ks="0,1,0". id : Field of View. This is the angle of the view cone of the camera. Whenever it's narrow, only a small area of the scene appears; whenever it's wide more area appears and objects look smaller. (2) The Orthographic Camera: ---------------------------- When we like to draw more precisive 3D drawings, like the ones used for Engineering, we normally don't like far sides of the object to appear smaller than the near ones since everything must be done with measurments. In order to generate this kind of drawings, the Orthographic camera is the one to select. It does not have a view cone. It actually has a view cylinder which must be as wide as the object in order to view it at 1:1 scale. To create an Orthographic camera call vm("cco") with the following parameters: os : Camera Position. See above. js : Look Direction. See above. ks : Up Direction. See above. id : Width. (3) The Matrix Camera: ---------------------- Normally, the Perspective and Orthographic cameras are all the Camera types which you may need. However, the WPF allows you to set the properties of a camera by defining its view and projection matrices. PC# allows you to use this type of camera to view the 3D scene which it generates for you, but it does not create the matrix camera itself. So, if you like to use a Matrix camera, do the following: (1) Create the view and projection transforms. (2) Create a matrix camera using the two transforms and make (mcp) its reference. (3) call vm("ccm") with no parameters. LIGHTS: ======= There are three major types of light: (1) Ambient Light: ------------------ This is a diffused light which is available everywhere but does not have a specific direction. It increases brightness of a 3D object while it cannot produce shadows or make object edges distinctive. For this reason, we normally don't use this light type alone. We mix it with other light types. It can be used as the brightness control of a 3D scene. (2) Directional Light: ---------------------- This is a light which is made of parallel rays with a specific intensity and direction. It can generate shadows and can cause sharp edges of the 3D object to appear. We may use more than one of this light type in order to illuminate the object from different directions. (3) Point Light: ---------------- This is "Light bulb" light. You may use any number of them in a 3D scene. The light rays of this type go evenly in all directions around the point where the light source is at. LIGHT PARAMETERS: ----------------- "Color" is a common parameter which you must specify for all types of light. The WPF 3D module applies some laws of physics regarding light reflection. An object looks dark unless it can reflect light and the color it appears at is the color of the light which it reflects. If we assume that the object's color was red and the light was green, the object will appear black no matter how strong the light is since the object cannot reflect green light. The only property which you supply when creating ambient light is the color code (cls) Point light requires additionally, the 3 coordinates of its location point assigned to (jd,kd,ld) Directional light requires (cls) and the 3 components of the vector specifying light direction assigned to (jd,kd,ld) also. HOW ARE LIGHTS CREATED IN PC#: ------------------------------ As you know PC# keeps only one object of each type at any moment. This made it possible to refer to each object by one unique name. For example (btp) is always the reference name of the last button object which you have called a PC# method to operate on. There are two advantages in that: (1) Memory Management: It regulates the size of the resources used by your program in order to guard against a crash. (2) Simplicity and error control: You can guarantee the name of the object which you like to operate on. This guards against errors and makes your job simpler, easier and more pleasant. If you have studied the "Pc# reference-Desktop" you already know how to use the "Present object" and what to do if you must keep more than one object at a time. With some objects like "Controls", keeping more than one object during the execution of your class is more than just a rare necessity. This is because you may like to create 3 buttons in one class and the user may click any of them at any time during execution, so the 3 objects must be always available. We use keynames to identify each object of this kind and PC# keeps all the object locations in its archives. Whenever you like to do an operation on button "bt0" for example, you supply method cm() with the keyname "bt0" assigned to (cs) The first thing the method does is looking through the archives to find the object of this button and making (btp) its reference. After the execution of this operation and before calling the method to operate on a new button, you can guarantee that (btp) is a reference to your button's object. If you like (btp) to be the reference of any button but you have no need to perform an operation, call cm("O") supplying it with the button's keyname. Let us now return to the main subject. You have a need for only one Camera in a 3D scene, so PC# has assigned 3 names for the 3 Camera objects which are (pcp), (ocp) and (mcp) When we come to "Lights", you may like to have more than one directional light or point light. So, we need to use the same technique which we use with controls. To create a light or perform any operation on a light, you need to supply its keyname assigned to (cs) The first 2 chars for the keyname of each light type are as follows: al: for Ambient light. dl: for Directional light. pl: for Point light. So, "al0","dl5" and "pl7" are valid keynames for lights. The 3 present objects for the 3 light types are (alp), (dlp) and (plp) We can install upto 10 different lights in a 3D scene. EXAMPLES: --------- cs="al0";cls="s0";vm("cla"); // Create ambient light, gray in color. cs="pl5";jd=kd=ld=100;vm("slp"); // Set the position of a point light at (100,100,100) cs="dl5";jd=kd=ld=-100;vm("sld");// Set the direction of a directional light at (-100,-100,-100) About the next example: ======================= The next example is very useful since it teachs you all about camera types, locations and directions. It also teaches you light types, how to create them and how to modify them after being created. It shows you how to move the Camera in a circle above the object while constantly pointing at the object in order to view it from all directions. This example is also an application on using check box and radio button groups. They work identically as they do in class (pcs) so, if you need more explanation regarding them, review example 3 of the chapter "Using Controls". ============================================================================================== Example 11: Create an eight sides cylinder. View it with a camera located at max (x,y,z) corner. Illuminate it with 4 lights. One directional light pointing to it from front top left corner, one directional light pointing to it from rear top right corner, one point light at top-center and an ambient light. Show the effect of switching between perspective and orthographic camera types. Also show the effect of eliminating one or more of created lights. Show how to dim and brighten the scene by adjusting the intensity of the ambient light and how to see object from all directions by rotating the camera over 360 degrees using slider controls. ============================================================================================== //assembly ms1.exe; public class a : ms1 { // using pcs3 public override void init() { base.init(); } public override void setup() { PageNumber=11;base.setup(); // Execute master class's setup() supplying it with page no. //----------------------------------- gr3 Contents ----------------------------------- cns="gr3"; // gr3 is divided into 3 col's. cs="gr4";j=0;oxd=0.30;ds="w";cls="S9y7";fns="tr12";cm("i"); cs="gr5";j=1;k=0;oxd=0.40;ds="c";cls="S9y7";fns="crb10";cm("i"); cs="gr6";j=2;k=0;oxd=0.30;ds="e";cls="S9y7";fns="crb10";cm("i"); //----------------------------------- gr4 Contents ----------------------------------- cns="gr4"; // gr4 is divided into 6 rows. cs="lb0";cis="LIGHT SELECTION";k=0;ds="c";oyd=0.1;cls="r0y7";fns="trb12";cm("i"); cs="cb00";cis="Front Directional Light";k=1;ds="w";cus="1"; oyd=0.1;cls="S9s9";fns="trb12";cm("i"); cs="cb01";cis="Rear Directional Light";k=2;ds="w";cus="1"; oyd=0.1;cls="S9s9";fns="trb12";cm("i"); cs="cb02";cis="Top Point Light";k=3;ds="w";cus="1";oyd=0.1;cls="S9s9";fns="trb12";cm("i"); cs="bt0";cis="Select Lights";k=4;ds="c";oyd=0.2;cls="r0g7";fns="trb12";cm("i"); cs="sl0";cis="Ambient Light Intensity\n 0 5 10";os="n";k=5;oyd=0.4; js="0,10";cus="5";lf=160;ds="s";cls="S9b2";fns="crb12";cm("i"); //----------------------------------- gr5 Contents ----------------------------------- cns="gr5"; // gr5 is not divided. cs="im1";cis="\nCamera and Light Effects";os="s";ds="c";ims="";lf=of=220;fns="trb16";cm("i"); //----------------------------------- gr6 Contents ----------------------------------- cns="gr6"; // gr6 is divided into 6 rows. cs="lb1";cis="CAMERA SELECTION";k=0;ds="c";oyd=0.1;cls="roy7";fns="trb12";cm("i"); cs="rb00";cis="Perspective Camera";k=1;ds="w";cus="1";oyd=0.1;cls="S9s9";fns="trb12";cm("i"); cs="rb01";cis="Orthographic Camera";k=2;ds="w";oyd=0.1;cls="S9s9";fns="trb12";cm("i"); cs="bt1";cis="Select Camera";k=4;ds="c";oyd=0.2;cls="r0g7";fns="trb12";cm("i"); cs="sl1";cis=" Camera Position\n-180 0 +180";os="n";k=5;oyd=0.4; js="0,10";cus="5";lf=160;ds="s";cls="S9b2";fns="crb12";cm("i"); } public override void update() { //------------------------------- Ambient Light adjustment ------------------------------ if ("sl0".Equals(cs)) { // If Ambient Light control slider activated: if (od<5) { // If pointer was at the darker half of the control: cls="S"+(9-(int)(od*9/5)); // Set the corresponding color code. } else { // Else, if pointer was at lighter half of the control: od-=5; // Adjust reading to fit the color code cls="s"+((int)(od*9/5)); // Set the corresponding color code. } cs="al0";vm("slc"); // Set ambient light color accordingly. } //------------------------------------ Camera Rotation ---------------------------------- else if ("sl1".Equals(cs)) { // If Camera rotation slider activated: // The object is considered to be at the center of a (220 X 220 X 220) room. The Camera is // at its ceiling which is parallel to the xz plane at a height of (y=110), It rotates // around ceiling center at a radius of 110. Its initial position is at point (110,0) // making a startup angle of zero with the Z-axis projection on the ceiling plane. // The slider's range was set as (0:10) so we should multiply its readings by (36) to // adjust them to (-180:180) range. The Camera's z and x coordinates at any angle should // be [radius*cos(angle)] and [radius*sin(angle)] respectively. In order to make camera // always point at center, its "Look direction" Vector3D components are obtained by // negating its position coordinates. double angle=od*36; // Obtain rotation angle which corresponds to (od) od=angle;js="cos";um("mt");zd=-110*od; od=angle;js="sin";um("mt");xd=-110*od; jd=xd;kd=110;ld=zd;vm("scp"); // Apply received values to camera's postion. jd=-xd;kd=-110;ld=-zd;vm("scl"); // and to its look direction. } //------------------------------------ Lights Selection --------------------------------- else if ("bt0".Equals(cs)) { // If "Lights Selection" button clicked: cs="cb0*";cm("gu"); // Get update values of CheckBox group into CUS[] for (n=0;n<3;n++) { // Scan CUS[] rows (which correspond to CheckBox states) if(CUS[n]=="1") cls="s0"; // If this row contains "1". set color at initial color. else cls="S9"; // Else, make it black (meaning eliminate this light) if (n==0) cs="dl0"; // First row sets our front directional light. else if (n==1) cs="dl1"; // Second row sets our back directional light. else cs="pl0"; // Third row sets top point light. vm("slc"); // Set lights as this row requires. } // Repeat for all rows of array CUS[] } //------------------------------------ Camera Selection --------------------------------- else if ("bt1".Equals(cs)) { // If "Camera Selection" button clicked: cs="rb0*";cm("gu"); // Get index of selected radio button in (cui) os="0,110,110"; // Set values which are common for the 2 camera types js="0,-110,-110";ks="0,1,0"; // which are: position, look direction and up direction. if (cui==0) { // If Perspective camera was selected: id=90; // Set its "Field of view angle" at 90 degrees. vm("ccp"); // and recreate a Perspective camera. } else { // Else, if Orthographic camera was selected: id=220; // Set its "Width" property at (220) which is enough to vm("cco"); // view full object and recreate an orthographic camera. } } } public override void run() { cs="im1";gm("sdi"); // Set (im1) as graphical output device. cls="g0";id=3;gm("sps"); // Create a new pen/brush of solid green color. id=217;od=217;gm("crd"); // Create a new Rectangle and draw it at center. id=8;od=150;dd=-150;js="yz";gm("cCv"); // Get vertex data for Cylinder with 8 sides base. cls="S9r5";js="d";vm("cof"); // Create and draw object in red using diffuse material. //---- Startup Camera ---- os="0,110,110"; // Camera position = Point (0,110,110) js="0,-110,-110"; // Look direction = from camera position to center. ks="0,1,0"; // Up Direction = +ve (Y) id=90; // Field of view angle=90 degrees. vm("ccp"); // Create Perspective camera. //---- Startup Lights ---- // "dl0" illuminates object's front side. "dl1" illuminates its back side. "pl0" illuminates // its top and "al0" acts as a brightness control. cs="dl0";cls="s0";jd=110;kd=ld=-110;vm("cld");// dir light from top-left-out corner to center cs="dl1";cls="s0";jd=-110;kd=ld=110;vm("cld");// dir light from top-right-in corner to center cs="pl0";cls="s0";jd=ld=0;kd=110;vm("clp"); // point light at top center. cs="al0";cls="s0";vm("cla"); // ambient light. gm("fdi"); // Finish drawing to (im1) } } ---------------------------------------------------------------------------------------------- As you must have expected moving the slider (sl1) from end to end rotates object by 360 degrees. This is because rotating the camera around object means that the object's image in the camera is rotating by the same angle in the opposite direction. COMMENTS: ========= (1) When we created slider (sl1) we requested a range of (0:10), then we multiplied each reading which we received from the slider in method update() by 36 since actual range is (-180:180) Why did'nt we set range at (-180:180) or (0:360) to start with? If we did we could have ended with a slider which contains 360 tick marks instead of 10. A slider with 10 tick marks looks better. (2) In real life, objects can be bright enough to cause blindness while on the screen or on paper they are as bright as they can be when they appear in white color. Since we must show a clear difference between bright and dark spots in a 3D scene, we make gray the average shade. Most lights are created with color code "s0" which is for gray color. ==============================================================================================


BEST SELLERS FROM AMAZON.COM

Books, C Sharp  Books, .NET  Computers  Electronics  Industrial & Scientific Items  MP3 Downloads  DVD
Camera & Photo  Cell Phones & Services  Magazine Subscriptions  Office Products  On Demand Videos




=============================================================================================== ANIMATION ========= If you have studied the web examples of WPDIII and WPDIV, you know how to use JavaScript and class (pasp) to do several types of animations. The WPF includes an entire namespace for the purpose of animation. We like to simplify and implement the most usable ones and most importantly, make it easy for you to include multiple animations into one page. Our animated objects must be able to run together into one graphical output device or several graphical output devices in the same page. Both 2D and 3D objects must be possible to animate. What can we animate? -------------------- We can apply the following animations to a 2D object: (1) We can move the 2D object horizontally and vertically according to a preset formula. (2) We can scale the 2D object horizontally and vertically also according to a preset formula. (3) And We can rotate the 2D object according to a preset formula. Similarly, we can apply the following animations to a 3D object: (1) We can move the 3D along the x,y and z axes according to a preset formula. (2) We can scale the 3D object on the x,y and z directions also according to a preset formula. (3) And We can rotate the 3D object according to a preset formula. What are the preset formulae? ----------------------------- Whenever we call method vm() to animate a specific property of an object, we supply a time schedule which describes what the value of that property should be at each selected moment. For example, if we like to apply horizontal movement animation to an object, we call vm("apx") which is for animating the x-position of the object supplying it with a time schedule like this: O[0]=0;OS[0]="0"; // At start (meaning after zero seconds), Keep object at center (ie x=0) O[1]=2;OS[1]="100"; // After 2 seconds, object should be at position (x=100) O[2]=4;OS[2]="-100"; // After 4 seconds, object should be at position (x=-100) This formula is made of 3 steps. We are telling The WPF where the object should be at start, after 2 seconds and after 4 seconds. the object is not going to jump from (position 0) to (position 100) or from (position 100) to (position -100), it will move smoothly between the three points. The movement-time relation is linear. Arrays O[] and OS[] are used to specify the seconds and the property values. The reason we use OS[] for this job is that different properties may require values of different types. For example, rotation of a 3D object with changing both axis and angle, requires 4 numbers, the first three specify the axis vector and the fourth one specifies the angle. We supply the 4 numbers seperated with commas into a row of array OS[], like: OS[4]="1,0,0,45". What to do after the time schedule has been executed? ----------------------------------------------------- The default is to repeat the process in reverse direction, then repeat the entire process indefinitely. However you can overwrite the defaults with: jb=true: Means Do Not "Auto Reverse". j=repititions: If (j) was not assigned zero, Animation will perform a limited number of repititions then stops. The number of repititions is the value assigned to (j) Setting the animation time unit: -------------------------------- We have told you that the amounts you assign to O[] are times in seconds. This is true although there is more to it. The default time unit is a second, but you can change that if you want. If you set it at (0.5 seconds), O[0]=3 will mean O[0]=1.5 seconds in this case. To change the animation time unit to any value, assign that value to (id) and call vm("atu") When you set the begin time and the duration of two animation steps, you are usually interested in how the number of the two steps compare rather than what the numbers are. You may like the two steps to be equal in duration for example or one of them to be a multiple of the other. This is why it's easier and more convenient to set the time in units instead of setting it discretely. The default time unit is one second, but you may set it at any value which may contain fractions. How to write the Animation program: =================================== [A] Identify the object with a keyname: --------------------------------------- Since we may need to animate more than one 2D or 3D object in one page, we need to keep the objects which we intend to animate referenced all the time. So whatever applies to "Lights" applies to them. We need to use keynames to identify those objects. The first two char's of a 2D object's keyname is "g2" and the first two char's of 3D object's keyname is "g3". So, to create a square which you intend to animate later, you may use this code: cs="g20";id=od=100;gm("crd");// Create rect and draw it. Identify its Geometry with "g20" and to create a circular 3D cylinder which you intend to animate, you may use this code: id=40;od=90;dd=60;js="zy";gm("cCv"); // Obtain vertex data for a cylinder. cs="g30";cls="s9s9";js="d";vm("cof");// Create & fill it. Identify it with the keyname "g30" [B] Animate object's properties: -------------------------------- You may then make any number of calls to method vm() at the following modes: "apx": Animate x-position using supplied formula. "apy": Animate y-position using supplied formula. "apz": (For 3D objects only) Animate z-position using supplied formula. "asx": Animate x-Scale factor using supplied formula. "asy": Animate y-Scale factor using supplied formula. "asz": (For 3D objects only) Animate z-Scale factor using supplied formula. "ara": Animate rotation angle only using supplied formula. "arx": Animate rotation axis and angle only using supplied formula. You should precede your call with the following assignments: (1) The same keyname which you used when object was created assigned to (cs) (2) The preset formula as described before. Notice that rotation of a 2D object requires assigning angles only to OS[], while rotation of a 3D object may require assigning angles alone or vectors of rotation axes and the angles. Rows of array OS[] are assigned one number for all animation options except when you rotate both axis and angle of a 3D object. You assign OS[]'s row 4 numbers seperated with commas in this case. When you animate the angle alone of a 3D object, you need to assign the rotation axis vector components to (ks) while assigning angles only to each row of OS[]. (3) If you like to prevent "auto-reverse", supply (jb=true) (4) If you don't like the animation to repeat forever, assign the number of wanted repetitions to (j) [C] Set animation trigger: -------------------------- If you like the animation to start as soon as the page is loaded, call vm("at") with no parameters. If you like it to start when button "bt0" is clicked, receive the event in method update() and start the animation there. How to make object's color change during animation? =================================================== You don't need to animate the color. You can set lights of different colors around the object so whenever the object moves, its color changes because of light reflections. We'll demonstrate this in the next example. How to animate properties of an object by yourself? =================================================== The WPF animation namespace allows you to animate some properties which we have no animation methods for. If you must animate any of these properties you need to do the animation job by yourself. If you like to animate such properties of an object which PC# has created for you, you need to know the following: (1) (gmo) is the reference of the (Geometry) object of the last 2D object which PC# has created for you. (2) (gmp) is the reference of the (GeometryModel3D) object of the last 3D object which PC# has created for you. (3) (srp) is the reference of the (Storyboard) object declared in class (pcs3) All 3 reference names are declared public so you can operate on them. Let us assume that you like to make a 2D object swing between the 2 X-positions (x=5,x=-5), here is what to do: (1) Create a translate transform, assign a name to it and register it with: this.RegisterName(name,ref); where ref= Translate transform object reference and "name" is the name you assigned to it. (2) Create an animation object of the type you like (most likely will be DoubleAnimation in this case) and set it to change values according to your desired formula. (3) Set the "AutoReverse" and "RepeatBehavior" of the animation object. (4) Set the TargetName of the animation to the same name which you used in (1) as follows: Storyboard.SetTargetName(a,name); Where (a) is the Animation object ref. (5) Set the TargetProperty of the animation to the XProperty of the TranslateTransform: Storyboard.SetTarg