]> 4ch.mooo.com Git - 16.git/blob - 16/PCGPE10/TUT9.TXT
reverted my open watcom to 1.9 an recompiled everything~
[16.git] / 16 / PCGPE10 / TUT9.TXT
1                    ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸\r
2                    ³         W E L C O M E         ³\r
3                    ³  To the VGA Trainer Program   ³ ³\r
4                    ³              By               ³ ³\r
5                    ³      DENTHOR of ASPHYXIA      ³ ³ ³\r
6                    ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³\r
7                      ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³\r
8                        ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
9 \r
10                            --==[ PART 9 ]==--\r
11 \r
12 \r
13 \r
14 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
15 þ Introduction\r
16 \r
17 Hi there! ASPHYXIA is BACK with our first MegaDemo, Psycho Neurosis! A\r
18 paltry 1.3MB download is all it takes to see the group from Durbs first\r
19 major production! We are quite proud of it, and think you should see it\r
20 ;)\r
21 \r
22 Secondly, I released a small little trainer (a trainerette ;-)) on\r
23 RsaPROG and Connexctix BBS mail, also on the ASPHYXIA BBS as COPPERS.ZIP\r
24 It is a small Pascal program demonstrating how to display copper bars in\r
25 text mode. Also includes a check for horizontal retrace (A lot of people\r
26 wanted it, that is why I wrote the program) (ASPHYXIA ... first with the\r
27 trainer goodies ;-)  aargh, sorry, had to be done ))\r
28 \r
29 Thirdly, sorry about the problems with Tut 8! If you had all the\r
30 checking on, the tutorial would probably die on the first points. The\r
31 reason is this : in the first loop, we have DrawPoints then\r
32 RotatePoints. The variables used in DrawPoints are set in RotatePoints,\r
33 so if you put RotatePoints before DrawPoints, the program should work\r
34 fine. Alternatively, turn off error checking 8-)\r
35 \r
36 Fourthly, I have had a surprisingly large number of people saying that\r
37 "I get this, like, strange '286 instructions not enabled' message!\r
38 What's wrong with your code, dude?"  To all of you, get into Pascal, hit\r
39 Alt-O (for options), hit enter and a 2 (for Enable 286 instructions). Hard\r
40 hey? Doesn't anyone EVER set up their version of Pascal?\r
41 \r
42 Now, on to todays tutorial! 3D solids. That is what the people wanted,\r
43 that is what the people get! This tutorial is mainly on how to draw the\r
44 polygon on screen. For details on how the 3D stuff works, check out tut\r
45 8.\r
46 \r
47 \r
48 \r
49 If you would like to contact me, or the team, there are many ways you\r
50 can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail\r
51                   on the ASPHYXIA BBS.\r
52             2) Write to Denthor, EzE or Goth on Connectix.\r
53             3) Write to :  Grant Smith\r
54                            P.O.Box 270 Kloof\r
55                            3640\r
56                            Natal\r
57             4) Call me (Grant Smith) at (031) 73 2129 (leave a message if you\r
58                   call during varsity)\r
59             5) Write to mcphail@beastie.cs.und.ac.za on InterNet, and\r
60                   mention the word Denthor near the top of the letter.\r
61 \r
62 NB : If you are a representative of a company or BBS, and want ASPHYXIA\r
63        to do you a demo, leave mail to me; we can discuss it.\r
64 NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling\r
65         quite lonely and want to meet/help out/exchange code with other demo\r
66         groups. What do you have to lose? Leave a message here and we can work\r
67         out how to transfer it. We really want to hear from you!\r
68 \r
69 \r
70 \r
71 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
72 þ How to draw a polygon\r
73 \r
74 Sounds easy enough, right? WRONG! There are many, many different ways to\r
75 go about this, and today I'll only be showing you one. Please don't take\r
76 what is written here as anything approaching the best method, it is just\r
77 here to get you on your way...\r
78 \r
79 The procedure I will be using here is based on something most of us\r
80 learned in standard eight ... I think. I seem to recall doing something\r
81 like this in Mrs. Reids maths class all those years ago ;)\r
82 \r
83 Take two points, x1,y1 and x2,y2. Draw them :\r
84 \r
85                   + (x1,y1)\r
86                    \\r
87                      \  <-- Point a somewhere along the line\r
88                        \\r
89                          + (x2,y2)\r
90 \r
91 Right, so what we have to do is this : if we know the y-coord of a, what\r
92 is it's x-coord? To prove the method we will give the points random\r
93 values.\r
94 \r
95                  + (2,10)\r
96                   \\r
97                     \  <-- a.y = 12\r
98                       \\r
99                         +  (15,30)\r
100 \r
101 Right. Simple enough problem. This is how we do it :\r
102    (a.y-y1) = (12 - 10)  {to get a.y as though y1 was zero}\r
103    *(x2-x1) = *(15 - 2)  {the total x-length of the line}\r
104    /(y2-y1) = /(30 - 10) {the total y-length of the line}\r
105         +x1 = +2         { to get the equation back to real coords}\r
106 \r
107 So our equation is :  (a.y-y1)*(x2-x1)/(y2-y1)+x4    or\r
108                       (12-10)*(15-2)/(30-10)+2\r
109       which gives you :\r
110                       2*13/20+2 = 26/20+2\r
111                                 = 3.3\r
112 \r
113 That means that along the line with y=12, x is equal to 3.3. Since we\r
114 are not concerned with the decimal place, we replace the  /  with a div,\r
115 which in Pascal gives us an integer result, and is faster too. All well\r
116 and good, I hear you cry, but what does this have to do with life and\r
117 how it relates to polygons in general. The answer is simple. For each of\r
118 the four sides of the polygon we do the above test for each y line. We\r
119 store the smallest and the largest x values into separate variables for\r
120 each line, and draw a horizontal line between them. Ta-Dah! We have a\r
121 cool polygon!\r
122 \r
123 For example : Two lines going down :\r
124     \r
125                 +             +\r
126                / <-x1     x2->|   <--For this y line\r
127              /                |\r
128            +                  +\r
129 \r
130 Find x1 and x2 for that y, then draw a line between them. Repeat for all\r
131 y values.\r
132 \r
133 Of course, it's not as simple as that. We have to make sure we only\r
134 check those y lines that contain the polygon (a simple min y, max y test\r
135 for all the points). We also have to check that the line we are\r
136 calculating actually extends as far as where our current y is (check\r
137 that the point is between both y's). We have to compare each x to see\r
138 weather it is smaller then the minimum x value so far, or bigger then\r
139 the maximum (the original x min is set as a high number, and the x max\r
140 is set as a small number). We must also check that we only draw to the\r
141 place that we can see ( 0-319 on the x ; 0-199 on the y (the size of the\r
142 MCGA screen))\r
143 \r
144 To see how this looks in practice, have a look at the sample code\r
145 provided. (Mrs. Reid would probably kill me for the above explanation,\r
146 so when you learn it in school, split it up into thousands of smaller\r
147 equations to get the same answer ;))\r
148 \r
149 Okay, that's it! What's that? How do you draw a vertical line? Thats\r
150 simple ...\r
151 \r
152 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
153 þ Drawing a vertical line\r
154 \r
155 Right, this is a lot easier than drawing a normal line (Tut 5 .. I\r
156 think), because you stay on the same y value. So, what you do is you set\r
157 ES to the screen you want to write to, and get DI to the start of the\r
158 y-line (see earlier trainers for a description of how SEGMENT:OFFSET\r
159 works.\r
160 \r
161 IN   : x1 , x2, y, color, where\r
162 \r
163            asm\r
164              mov    ax,where\r
165              mov    es,ax\r
166              mov    di,y\r
167              mov    ax,y\r
168              shl    di,8   { di:=di*256 }\r
169              shl    ax,6   { ax:=ax*64 }\r
170              add    di,ax  { di := (y*256)+(y*64) := y*320 Faster then a\r
171                              straight multiplication }\r
172 \r
173 Right, now you add the first x value to get your startoff.\r
174              add    di,x1\r
175 Move the color to store into ah and al\r
176              mov    al,color\r
177              mov    ah,al       { ah:=al:=color }\r
178 then get CX equal to how many pixels across you want to go\r
179              mov    cx,x2\r
180              sub    cx,x1   { cx:=x2-x1 }\r
181 Okay, as we all know, moving a word is a lot faster then moving a byte,\r
182 so we halve CX\r
183              shr    cx,1    { cx:=cx/2 }\r
184 but what happens if CX was an odd number. After a shift, the value of\r
185 the last number is placed in the carry flag, so what we do is jump over\r
186 a single byte move if the carry flag is zero, or execute it if it is\r
187 one.\r
188             jnc     @Start  { If there is no carry, jump to label Start }\r
189             stosb           { ES:[DI]:=al ; increment DI }\r
190         @Start :            { Label Start }\r
191             rep     stosw   { ES:[DI]:=ax ; DI:=DI+2; repeat CX times }\r
192 \r
193 Right, the finished product looks like this :\r
194 \r
195 Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;\r
196   { This draws a horizontal line from x1 to x2 on line y in color col }\r
197 asm\r
198   mov   ax,where\r
199   mov   es,ax\r
200   mov   ax,y\r
201   mov   di,ax\r
202   shl   ax,8\r
203   shl   di,6\r
204   add   di,ax\r
205   add   di,x1\r
206 \r
207   mov   al,col\r
208   mov   ah,al\r
209   mov   cx,x2\r
210   sub   cx,x1\r
211   shr   cx,1\r
212   jnc   @start\r
213   stosb\r
214 @Start :\r
215   rep   stosw\r
216 end;\r
217 \r
218 Done!\r
219 \r
220 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\r
221 þ  In closing\r
222 \r
223 This 3D system is still not perfect. It needs to be faster, and now I\r
224 have also dumped the problem of face-sorting on you! Nyahahahaha!\r
225 \r
226            [ My sister and I were driving along the other day when she\r
227                asked me, what would I like for my computer.\r
228              I thought long and hard about it, and came up with the\r
229                following hypothesis. When a girl gets a Barbie doll, she\r
230                then wants the extra ballgown for the doll, then the\r
231                hairbrush, and the car, and the house, and the friends\r
232                etc.\r
233              When a guy gets a computer, he wants the extra memory, the\r
234                bigger hard drive, the maths co-pro, the better\r
235                motherboard, the latest software, and the bigger monitor\r
236                etc.\r
237              I told my sister all of this, and finished up with : "So as\r
238                you can see, computers are Barbie dolls for MEN!"\r
239              She called me a chauvinist. And hit me. Hard.\r
240                                                                    ]\r
241                                                        - Grant Smith\r
242                                                            19:24\r
243                                                              26/2/94\r
244 \r
245 See you next time!\r
246   - Denthor\r
247 \r
248 These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)\r
249 \r
250 ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ»\r
251 ºBBS Name                  ºTelephone No.   ºOpen ºMsgºFileºPastº\r
252 ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹\r
253 ºASPHYXIA BBS #1           º(031) 765-5312  ºALL  º * º *  º *  º\r
254 ºASPHYXIA BBS #2           º(031) 765-6293  ºALL  º * º *  º *  º\r
255 ºConnectix BBS             º(031) 266-9992  ºALL  º   º *  º *  º\r
256 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ\r
257 \r
258 Open = Open at all times or only A/H\r
259 Msg  = Available in message base\r
260 File = Available in file base\r
261 Past = Previous Parts available\r
262 \r
263 Does no other BBS's ANYWHERE carry the trainer? Am I writing this for\r
264 three people who get it from one of these BBS's each week? Should I go\r
265 on? (Hehehehe ... I was pleased to note that Tut 8 was THE most\r
266 downloaded file from ASPHYXIA BBS last month ... )       \r
267 \r
268 \r
269 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ\r
270 ³ TUTPROG9.PAS ³\r
271 ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ\r
272 \r
273 {$X+}\r
274 USES Crt;\r
275 \r
276 CONST VGA = $A000;\r
277       maxpolys = 5;\r
278       A : Array [1..maxpolys,1..4,1..3] of integer =\r
279         (\r
280          ((-10,10,0),(-2,-10,0),(0,-10,0),(-5,10,0)),\r
281          ((10,10,0),(2,-10,0),(0,-10,0),(5,10,0)),\r
282          ((-2,-10,0),(2,-10,0),(2,-5,0),(-2,-5,0)),\r
283          ((-6,0,0),(6,0,0),(7,5,0),(-7,5,0)),\r
284          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))\r
285         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }\r
286             { (X2,Y2,Z2) ... for the 4 points of a poly }\r
287      S : Array [1..maxpolys,1..4,1..3] of integer =\r
288         (\r
289          ((-10,-10,0),(10,-10,0),(10,-7,0),(-10,-7,0)),\r
290          ((-10,10,0),(10,10,0),(10,7,0),(-10,7,0)),\r
291          ((-10,1,0),(10,1,0),(10,-2,0),(-10,-2,0)),\r
292          ((-10,-8,0),(-7,-8,0),(-7,0,0),(-10,0,0)),\r
293          ((10,8,0),(7,8,0),(7,0,0),(10,0,0))\r
294         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }\r
295             { (X2,Y2,Z2) ... for the 4 points of a poly }\r
296      P : Array [1..maxpolys,1..4,1..3] of integer =\r
297         (\r
298          ((-10,-10,0),(-7,-10,0),(-7,10,0),(-10,10,0)),\r
299          ((10,-10,0),(7,-10,0),(7,0,0),(10,0,0)),\r
300          ((-9,-10,0),(9,-10,0),(9,-7,0),(-9,-7,0)),\r
301          ((-9,-1,0),(9,-1,0),(9,2,0),(-9,2,0)),\r
302          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))\r
303         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }\r
304             { (X2,Y2,Z2) ... for the 4 points of a poly }\r
305      H : Array [1..maxpolys,1..4,1..3] of integer =\r
306         (\r
307          ((-10,-10,0),(-7,-10,0),(-7,10,0),(-10,10,0)),\r
308          ((10,-10,0),(7,-10,0),(7,10,0),(10,10,0)),\r
309          ((-9,-1,0),(9,-1,0),(9,2,0),(-9,2,0)),\r
310          ((0,0,0),(0,0,0),(0,0,0),(0,0,0)),\r
311          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))\r
312         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }\r
313             { (X2,Y2,Z2) ... for the 4 points of a poly }\r
314      Y : Array [1..maxpolys,1..4,1..3] of integer =\r
315         (\r
316          ((-7,-10,0),(0,-3,0),(0,0,0),(-10,-7,0)),\r
317          ((7,-10,0),(0,-3,0),(0,0,0),(10,-7,0)),\r
318          ((-2,-3,0),(2,-3,0),(2,10,0),(-2,10,0)),\r
319          ((0,0,0),(0,0,0),(0,0,0),(0,0,0)),\r
320          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))\r
321         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }\r
322             { (X2,Y2,Z2) ... for the 4 points of a poly }\r
323      X : Array [1..maxpolys,1..4,1..3] of integer =\r
324         (\r
325          ((-7,-10,0),(10,7,0),(7,10,0),(-10,-7,0)),\r
326          ((7,-10,0),(-10,7,0),(-7,10,0),(10,-7,0)),\r
327          ((0,0,0),(0,0,0),(0,0,0),(0,0,0)),\r
328          ((0,0,0),(0,0,0),(0,0,0),(0,0,0)),\r
329          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))\r
330         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }\r
331             { (X2,Y2,Z2) ... for the 4 points of a poly }\r
332      I : Array [1..maxpolys,1..4,1..3] of integer =\r
333         (\r
334          ((-10,-10,0),(10,-10,0),(10,-7,0),(-10,-7,0)),\r
335          ((-10,10,0),(10,10,0),(10,7,0),(-10,7,0)),\r
336          ((-2,-9,0),(2,-9,0),(2,9,0),(-2,9,0)),\r
337          ((0,0,0),(0,0,0),(0,0,0),(0,0,0)),\r
338          ((0,0,0),(0,0,0),(0,0,0),(0,0,0))\r
339         );  { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }\r
340             { (X2,Y2,Z2) ... for the 4 points of a poly }\r
341 \r
342 \r
343 Type Point = Record\r
344                x,y,z:real;                { The data on every point we rotate}\r
345              END;\r
346      Virtual = Array [1..64000] of byte;  { The size of our Virtual Screen }\r
347      VirtPtr = ^Virtual;                  { Pointer to the virtual screen }\r
348 \r
349 \r
350 VAR Lines : Array [1..maxpolys,1..4] of Point;  { The base object rotated }\r
351     Translated : Array [1..maxpolys,1..4] of Point; { The rotated object }\r
352     Xoff,Yoff,Zoff:Integer;               { Used for movement of the object }\r
353     lookup : Array [0..360,1..2] of real; { Our sin and cos lookup table }\r
354     Virscr : VirtPtr;                     { Our first Virtual screen }\r
355     Vaddr  : word;                        { The segment of our virtual screen}\r
356 \r
357 \r
358 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
359 Procedure SetMCGA;  { This procedure gets you into 320x200x256 mode. }\r
360 BEGIN\r
361   asm\r
362      mov        ax,0013h\r
363      int        10h\r
364   end;\r
365 END;\r
366 \r
367 \r
368 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
369 Procedure SetText;  { This procedure returns you to text mode.  }\r
370 BEGIN\r
371   asm\r
372      mov        ax,0003h\r
373      int        10h\r
374   end;\r
375 END;\r
376 \r
377 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
378 Procedure Cls (Where:word;Col : Byte);\r
379    { This clears the screen to the specified color }\r
380 BEGIN\r
381      asm\r
382         push    es\r
383         mov     cx, 32000;\r
384         mov     es,[where]\r
385         xor     di,di\r
386         mov     al,[col]\r
387         mov     ah,al\r
388         rep     stosw\r
389         pop     es\r
390      End;\r
391 END;\r
392 \r
393 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
394 Procedure SetUpVirtual;\r
395    { This sets up the memory needed for the virtual screen }\r
396 BEGIN\r
397   GetMem (VirScr,64000);\r
398   vaddr := seg (virscr^);\r
399 END;\r
400 \r
401 \r
402 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
403 Procedure ShutDown;\r
404    { This frees the memory used by the virtual screen }\r
405 BEGIN\r
406   FreeMem (VirScr,64000);\r
407 END;\r
408 \r
409 \r
410 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
411 procedure flip(source,dest:Word);\r
412   { This copies the entire screen at "source" to destination }\r
413 begin\r
414   asm\r
415     push    ds\r
416     mov     ax, [Dest]\r
417     mov     es, ax\r
418     mov     ax, [Source]\r
419     mov     ds, ax\r
420     xor     si, si\r
421     xor     di, di\r
422     mov     cx, 32000\r
423     rep     movsw\r
424     pop     ds\r
425   end;\r
426 end;\r
427 \r
428 \r
429 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
430 Procedure Pal(Col,R,G,B : Byte);\r
431   { This sets the Red, Green and Blue values of a certain color }\r
432 Begin\r
433    asm\r
434       mov    dx,3c8h\r
435       mov    al,[col]\r
436       out    dx,al\r
437       inc    dx\r
438       mov    al,[r]\r
439       out    dx,al\r
440       mov    al,[g]\r
441       out    dx,al\r
442       mov    al,[b]\r
443       out    dx,al\r
444    end;\r
445 End;\r
446 \r
447 \r
448 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
449 Procedure Hline (x1,x2,y:word;col:byte;where:word); assembler;\r
450   { This draws a horizontal line from x1 to x2 on line y in color col }\r
451 asm\r
452   mov   ax,where\r
453   mov   es,ax\r
454   mov   ax,y\r
455   mov   di,ax\r
456   shl   ax,8\r
457   shl   di,6\r
458   add   di,ax\r
459   add   di,x1\r
460 \r
461   mov   al,col\r
462   mov   ah,al\r
463   mov   cx,x2\r
464   sub   cx,x1\r
465   shr   cx,1\r
466   jnc   @start\r
467   stosb\r
468 @Start :\r
469   rep   stosw\r
470 end;\r
471 \r
472 \r
473 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
474 Procedure DrawPoly(x1,y1,x2,y2,x3,y3,x4,y4:integer;color:byte;where:word);\r
475   { This draw a polygon with 4 points at x1,y1 , x2,y2 , x3,y3 , x4,y4\r
476     in color col }\r
477 var\r
478   x:integer;\r
479   mny,mxy:integer;\r
480   mnx,mxx,yc:integer;\r
481   mul1,div1,\r
482   mul2,div2,\r
483   mul3,div3,\r
484   mul4,div4:integer;\r
485 \r
486 begin\r
487   mny:=y1; mxy:=y1;\r
488   if y2<mny then mny:=y2;\r
489   if y2>mxy then mxy:=y2;\r
490   if y3<mny then mny:=y3;\r
491   if y3>mxy then mxy:=y3;    { Choose the min y mny and max y mxy }\r
492   if y4<mny then mny:=y4;\r
493   if y4>mxy then mxy:=y4;\r
494 \r
495   if mny<0 then mny:=0;\r
496   if mxy>199 then mxy:=199;\r
497   if mny>199 then exit;\r
498   if mxy<0 then exit;        { Verticle range checking }\r
499 \r
500   mul1:=x1-x4; div1:=y1-y4;\r
501   mul2:=x2-x1; div2:=y2-y1;\r
502   mul3:=x3-x2; div3:=y3-y2;\r
503   mul4:=x4-x3; div4:=y4-y3;  { Constansts needed for intersection calc }\r
504 \r
505   for yc:=mny to mxy do\r
506     begin\r
507       mnx:=320;\r
508       mxx:=-1;\r
509       if (y4>=yc) or (y1>=yc) then\r
510         if (y4<=yc) or (y1<=yc) then   { Check that yc is between y1 and y4 }\r
511           if not(y4=y1) then\r
512             begin\r
513               x:=(yc-y4)*mul1 div div1+x4; { Point of intersection on x axis }\r
514               if x<mnx then\r
515                 mnx:=x;\r
516               if x>mxx then\r
517                 mxx:=x;       { Set point as start or end of horiz line }\r
518             end;\r
519       if (y1>=yc) or (y2>=yc) then\r
520         if (y1<=yc) or (y2<=yc) then   { Check that yc is between y1 and y2 }\r
521           if not(y1=y2) then\r
522             begin\r
523               x:=(yc-y1)*mul2 div div2+x1; { Point of intersection on x axis }\r
524               if x<mnx then\r
525                 mnx:=x;\r
526               if x>mxx then\r
527                 mxx:=x;       { Set point as start or end of horiz line }\r
528             end;\r
529       if (y2>=yc) or (y3>=yc) then\r
530         if (y2<=yc) or (y3<=yc) then   { Check that yc is between y2 and y3 }\r
531           if not(y2=y3) then\r
532             begin\r
533               x:=(yc-y2)*mul3 div div3+x2; { Point of intersection on x axis }\r
534               if x<mnx then\r
535                 mnx:=x;\r
536               if x>mxx then\r
537                 mxx:=x;       { Set point as start or end of horiz line }\r
538             end;\r
539       if (y3>=yc) or (y4>=yc) then\r
540         if (y3<=yc) or (y4<=yc) then   { Check that yc is between y3 and y4 }\r
541           if not(y3=y4) then\r
542             begin\r
543               x:=(yc-y3)*mul4 div div4+x3; { Point of intersection on x axis }\r
544               if x<mnx then\r
545                 mnx:=x;\r
546               if x>mxx then\r
547                 mxx:=x;       { Set point as start or end of horiz line }\r
548             end;\r
549       if mnx<0 then\r
550         mnx:=0;\r
551       if mxx>319 then\r
552         mxx:=319;          { Range checking on horizontal line }\r
553       if mnx<=mxx then\r
554         hline (mnx,mxx,yc,color,where);   { Draw the horizontal line }\r
555     end;\r
556   end;\r
557 \r
558 \r
559 \r
560 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
561 Function rad (theta : real) : real;\r
562   {  This calculates the degrees of an angle }\r
563 BEGIN\r
564   rad := theta * pi / 180\r
565 END;\r
566 \r
567 \r
568 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
569 Procedure SetUpPoints;\r
570   { This creates the lookup table }\r
571 VAR loop1,loop2:integer;\r
572 BEGIN\r
573   For loop1:=0 to 360 do BEGIN\r
574     lookup [loop1,1]:=sin (rad (loop1));\r
575     lookup [loop1,2]:=cos (rad (loop1));\r
576   END;\r
577 END;\r
578 \r
579 \r
580 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
581 Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);\r
582   { This puts a pixel on the screen by writing directly to memory. }\r
583 BEGIN\r
584   Asm\r
585     mov     ax,[where]\r
586     mov     es,ax\r
587     mov     bx,[X]\r
588     mov     dx,[Y]\r
589     mov     di,bx\r
590     mov     bx, dx                  {; bx = dx}\r
591     shl     dx, 8\r
592     shl     bx, 6\r
593     add     dx, bx                  {; dx = dx + bx (ie y*320)}\r
594     add     di, dx                  {; finalise location}\r
595     mov     al, [Col]\r
596     stosb\r
597   End;\r
598 END;\r
599 \r
600 \r
601 \r
602 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
603 Procedure RotatePoints (X,Y,Z:Integer);\r
604   { This rotates object lines by X,Y and Z; then places the result in\r
605     TRANSLATED }\r
606 VAR loop1,loop2:integer;\r
607     temp:point;\r
608 BEGIN\r
609   For loop1:=1 to maxpolys do BEGIN\r
610     For loop2:=1 to 4 do BEGIN\r
611       temp.x:=lines[loop1,loop2].x;\r
612       temp.y:=lookup[x,2]*lines[loop1,loop2].y - lookup[x,1]*lines[loop1,loop2].z;\r
613       temp.z:=lookup[x,1]*lines[loop1,loop2].y + lookup[x,2]*lines[loop1,loop2].z;\r
614 \r
615       translated[loop1,loop2]:=temp;\r
616 \r
617       If y>0 then BEGIN\r
618         temp.x:=lookup[y,2]*translated[loop1,loop2].x - lookup[y,1]*translated[loop1,loop2].y;\r
619         temp.y:=lookup[y,1]*translated[loop1,loop2].x + lookup[y,2]*translated[loop1,loop2].y;\r
620         temp.z:=translated[loop1,loop2].z;\r
621         translated[loop1,loop2]:=temp;\r
622       END;\r
623 \r
624       If z>0 then BEGIN\r
625         temp.x:=lookup[z,2]*translated[loop1,loop2].x + lookup[z,1]*translated[loop1,loop2].z;\r
626         temp.y:=translated[loop1,loop2].y;\r
627         temp.z:=-lookup[z,1]*translated[loop1,loop2].x + lookup[z,2]*translated[loop1,loop2].z;\r
628         translated[loop1,loop2]:=temp;\r
629       END;\r
630     END;\r
631   END;\r
632 END;\r
633 \r
634 \r
635 \r
636 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
637 Procedure DrawPoints;\r
638   { This draws the translated object to the virtual screen }\r
639 VAR loop1:Integer;\r
640     nx,ny,nx2,ny2,nx3,ny3,nx4,ny4:integer;\r
641     temp:integer;\r
642 BEGIN\r
643   For loop1:=1 to maxpolys do BEGIN\r
644     If (translated[loop1,1].z+zoff<0) and (translated[loop1,2].z+zoff<0) and\r
645        (translated[loop1,3].z+zoff<0) and (translated[loop1,4].z+zoff<0) then BEGIN\r
646       temp:=round (translated[loop1,1].z+zoff);\r
647       nx :=round (256*translated[loop1,1].X) div temp+xoff;\r
648       ny :=round (256*translated[loop1,1].Y) div temp+yoff;\r
649       temp:=round (translated[loop1,2].z+zoff);\r
650       nx2:=round (256*translated[loop1,2].X) div temp+xoff;\r
651       ny2:=round (256*translated[loop1,2].Y) div temp+yoff;\r
652       temp:=round (translated[loop1,3].z+zoff);\r
653       nx3:=round (256*translated[loop1,3].X) div temp+xoff;\r
654       ny3:=round (256*translated[loop1,3].Y) div temp+yoff;\r
655       temp:=round (translated[loop1,4].z+zoff);\r
656       nx4:=round (256*translated[loop1,4].X) div temp+xoff;\r
657       ny4:=round (256*translated[loop1,4].Y) div temp+yoff;\r
658       drawpoly (nx,ny,nx2,ny2,nx3,ny3,nx4,ny4,13,vaddr);\r
659     END;\r
660   END;\r
661 END;\r
662 \r
663 \r
664 \r
665 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}\r
666 Procedure MoveAround;\r
667   { This is the main display procedure. Firstly it brings the object towards\r
668     the viewer by increasing the Zoff, then passes control to the user }\r
669 VAR deg,loop1,loop2:integer;\r
670     ch:char;\r
671 \r
672   Procedure Whizz (sub:boolean);\r
673   VAR loop1:integer;\r
674   BEGIN\r
675     For loop1:=-64 to -5 do BEGIN\r
676       zoff:=loop1*8;\r
677       if sub then xoff:=xoff-7 else xoff:=xoff+7;\r
678       RotatePoints (deg,deg,deg);\r
679       DrawPoints;\r
680       flip (vaddr,vga);\r
681       Cls (vaddr,0);\r
682       deg:=(deg+5) mod 360;\r
683     END;\r
684   END;\r
685 \r
686 BEGIN\r
687   deg:=0;\r
688   ch:=#0;\r
689   Yoff:=100;\r
690   Xoff:=350;\r
691   Cls (vaddr,0);\r
692   For loop1:=1 to maxpolys do\r
693     For loop2:=1 to 4 do BEGIN\r
694       Lines [loop1,loop2].x:=a [loop1,loop2,1];\r
695       Lines [loop1,loop2].y:=a [loop1,loop2,2];\r
696       Lines [loop1,loop2].z:=a [loop1,loop2,3];\r
697     END;\r
698   Whizz (TRUE);\r
699 \r
700   For loop1:=1 to maxpolys do\r
701     For loop2:=1 to 4 do BEGIN\r
702       Lines [loop1,loop2].x:=s [loop1,loop2,1];\r
703       Lines [loop1,loop2].y:=s [loop1,loop2,2];\r
704       Lines [loop1,loop2].z:=s [loop1,loop2,3];\r
705     END;\r
706   Whizz (FALSE);\r
707 \r
708   For loop1:=1 to maxpolys do\r
709     For loop2:=1 to 4 do BEGIN\r
710       Lines [loop1,loop2].x:=p [loop1,loop2,1];\r
711       Lines [loop1,loop2].y:=p [loop1,loop2,2];\r
712       Lines [loop1,loop2].z:=p [loop1,loop2,3];\r
713     END;\r
714   Whizz (TRUE);\r
715 \r
716   For loop1:=1 to maxpolys do\r
717     For loop2:=1 to 4 do BEGIN\r
718       Lines [loop1,loop2].x:=h [loop1,loop2,1];\r
719       Lines [loop1,loop2].y:=h [loop1,loop2,2];\r
720       Lines [loop1,loop2].z:=h [loop1,loop2,3];\r
721     END;\r
722   Whizz (FALSE);\r
723 \r
724   For loop1:=1 to maxpolys do\r
725     For loop2:=1 to 4 do BEGIN\r
726       Lines [loop1,loop2].x:=y [loop1,loop2,1];\r
727       Lines [loop1,loop2].y:=y [loop1,loop2,2];\r
728       Lines [loop1,loop2].z:=y [loop1,loop2,3];\r
729     END;\r
730   Whizz (TRUE);\r
731 \r
732   For loop1:=1 to maxpolys do\r
733     For loop2:=1 to 4 do BEGIN\r
734       Lines [loop1,loop2].x:=x [loop1,loop2,1];\r
735       Lines [loop1,loop2].y:=x [loop1,loop2,2];\r
736       Lines [loop1,loop2].z:=x [loop1,loop2,3];\r
737     END;\r
738   Whizz (FALSE);\r
739 \r
740   For loop1:=1 to maxpolys do\r
741     For loop2:=1 to 4 do BEGIN\r
742       Lines [loop1,loop2].x:=i [loop1,loop2,1];\r
743       Lines [loop1,loop2].y:=i [loop1,loop2,2];\r
744       Lines [loop1,loop2].z:=i [loop1,loop2,3];\r
745     END;\r
746   Whizz (TRUE);\r
747 \r
748   For loop1:=1 to maxpolys do\r
749     For loop2:=1 to 4 do BEGIN\r
750       Lines [loop1,loop2].x:=a [loop1,loop2,1];\r
751       Lines [loop1,loop2].y:=a [loop1,loop2,2];\r
752       Lines [loop1,loop2].z:=a [loop1,loop2,3];\r
753     END;\r
754   Whizz (FALSE);\r
755 \r
756   cls (vaddr,0);\r
757   cls (vga,0);\r
758   Xoff := 160;\r
759 \r
760   Repeat\r
761     if keypressed then BEGIN\r
762       ch:=upcase (Readkey);\r
763       Case ch of 'A' : zoff:=zoff+5;\r
764                  'Z' : zoff:=zoff-5;\r
765                  ',' : xoff:=xoff-5;\r
766                  '.' : xoff:=xoff+5;\r
767                  'S' : yoff:=yoff-5;\r
768                  'X' : yoff:=yoff+5;\r
769       END;\r
770     END;\r
771     DrawPoints;\r
772     flip (vaddr,vga);\r
773     cls (vaddr,0);\r
774     RotatePoints (deg,deg,deg);\r
775     deg:=(deg+5) mod 360;\r
776   Until ch=#27;\r
777 END;\r
778 \r
779 \r
780 BEGIN\r
781   SetUpVirtual;\r
782   clrscr;\r
783   Writeln ('Hello there! Varsity has begun once again, so it is once again');\r
784   Writeln ('back to the grindstone ;-) ... anyway, this tutorial is, by');\r
785   Writeln ('popular demand, on poly-filling, in relation to 3-D solids.');\r
786   Writeln;\r
787   Writeln ('In this program, the letters of ASPHYXIA will fly past you. As you');\r
788   Writeln ('will see, they are solid, not wireframe. After the last letter has');\r
789   Writeln ('flown by, a large A will be left in the middle of the screen.');\r
790   Writeln;\r
791   Writeln ('You will be able to move it around the screen, and you will notice');\r
792   Writeln ('that it may have bits only half on the screen, i.e. clipping is');\r
793   Writeln ('perfomed. To control it use the following : "A" and "Z" control the Z');\r
794   Writeln ('movement, "," and "." control the X movement, and "S" and "X"');\r
795   Writeln ('control the Y movement. I have not included rotation control, but');\r
796   Writeln ('it should be easy enough to put in yourself ... if you have any');\r
797   Writeln ('hassles, leave me mail.');\r
798   Writeln;\r
799   Writeln ('I hope this is what you wanted...leave me mail for new ideas.');\r
800   writeln;\r
801   writeln;\r
802   Write ('  Hit any key to contine ...');\r
803   Readkey;\r
804   SetMCGA;\r
805   SetUpPoints;\r
806   MoveAround;\r
807   SetText;\r
808   ShutDown;\r
809   Writeln ('All done. This concludes the ninth sample program in the ASPHYXIA');\r
810   Writeln ('Training series. You may reach DENTHOR under the names of GRANT');\r
811   Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid');\r
812   Writeln ('Connectix BBS user, and occasionally read RSAProg.');\r
813   Writeln ('The numbers are available in the main text. You may also write to me at:');\r
814   Writeln ('             Grant Smith');\r
815   Writeln ('             P.O. Box 270');\r
816   Writeln ('             Kloof');\r
817   Writeln ('             3640');\r
818   Writeln ('I hope to hear from you soon!');\r
819   Writeln; Writeln;\r
820   Write   ('Hit any key to exit ...');\r
821   Readkey;\r
822 END.\r
823 \r