1 ÕÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ͸
\r
3 ³ To the VGA Trainer Program ³ ³
\r
5 ³ DENTHOR of ASPHYXIA ³ ³ ³
\r
6 ÔÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ; ³ ³
\r
7 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³
\r
8 ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
\r
14 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
17 Hello everybody! Christmas is over, the last of the chocolates have been
\r
18 eaten, so it's time to get on with this, the eighth part of the ASPHYXIA
\r
19 Demo Trainer Series. This particular part is primarily about 3-D, but
\r
20 also includes a bit on optimisation.
\r
22 If you are already a 3-D guru, you may as well skip this text file, have
\r
23 a quick look at the sample program then go back to sleep, because I am
\r
24 going to explain in minute detail exactly how the routines work ;)
\r
26 If you would like to contact me, or the team, there are many ways you
\r
27 can do it : 1) Write a message to Grant Smith/Denthor/Asphyxia in private mail
\r
28 on the ASPHYXIA BBS.
\r
29 2) Write a message in the Programming conference on the
\r
30 For Your Eyes Only BBS (of which I am the Moderator )
\r
31 This is preferred if you have a general programming query
\r
32 or problem others would benefit from.
\r
33 4) Write to Denthor, EzE or Goth on Connectix.
\r
34 5) Write to : Grant Smith
\r
38 6) Call me (Grant Smith) at (031) 73 2129 (leave a message if you
\r
39 call during varsity)
\r
40 7) Write to mcphail@beastie.cs.und.ac.za on InterNet, and
\r
41 mention the word Denthor near the top of the letter.
\r
43 NB : If you are a representative of a company or BBS, and want ASPHYXIA
\r
44 to do you a demo, leave mail to me; we can discuss it.
\r
45 NNB : If you have done/attempted a demo, SEND IT TO ME! We are feeling
\r
46 quite lonely and want to meet/help out/exchange code with other demo
\r
47 groups. What do you have to lose? Leave a message here and we can work
\r
48 out how to transfer it. We really want to hear from you!
\r
52 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
55 Before I begin with the note on 3-D, I would like to stress that many of
\r
56 these routines, and probably most of your own, could be sped up quite a
\r
57 bit with a little optimisation. One must realise, however, that you must
\r
58 take a look at WHAT to optimise ... converting a routine that is only
\r
59 called once at startup into a tightly coded assembler routine may show
\r
60 off your merits as a coder, but does absolutely nothing to speed up your
\r
61 program. Something that is called often per frame is something that
\r
62 needs to be as fast as possible. For some, a much used procedure is the
\r
63 PutPixel procedure. Here is the putpixel procedure I gave you last week:
\r
65 Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
\r
68 push ds { 14 clock ticks }
\r
70 mov ax,[where] { 8 }
\r
90 mov es:[di],ah { 10 }
\r
95 Total = 153 clock ticks
\r
96 NOTE : Don't take my clock ticks as gospel, I probably got one or two
\r
99 Right, now for some optimising. Firstly, if you have 286 instructions
\r
100 turned on, you may replace the 6 shl,1 with shl,6. Secondly, the Pascal
\r
101 compiler automatically pushes and pops ES, so those two lines may be
\r
102 removed. DS:[SI] is not altered in this procedure, so we may remove
\r
103 those too. Also, instead of moving COL into ah, we move it into AL and
\r
104 call stosb (es:[di]:=al; inc di). Let's have a look at the routine now :
\r
106 Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
\r
109 mov ax,[where] { 8 }
\r
122 mov al, [Col] { 8 }
\r
126 Total = 95 clock ticks
\r
128 Now, let us move the value of BX directly into DI, thereby removing a
\r
129 costly push and pop. The MOV and the XOR of DX can be replaced by it's
\r
130 equivalent, SHL DX,8
\r
132 Procedure Putpixel (X,Y : Integer; Col : Byte; where:word); assembler;
\r
134 mov ax,[where] { 8 }
\r
144 mov al, [Col] { 8 }
\r
147 Total = 71 clock ticks
\r
149 As you can see, we have brought the clock ticks down from 153 ticks to
\r
150 71 ticks ... quite an improvement. (The current ASPHYXIA putpixel takes
\r
151 48 clock ticks) . As you can see, by going through your routines a few
\r
152 times, you can spot and remove unnecessary instructions, thereby greatly
\r
153 increasing the speed of your program.
\r
156 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
157 þ Defining a 3-D object
\r
159 Drawing an object in 3-D is not that easy. Sitting down and plotting a
\r
160 list of X,Y and Z points can be a time consuming business. So, let us
\r
161 first look at the three axes you are drawing them on :
\r
170 X is the horisontal axis, from left to right. Y is the vertical axis,
\r
171 from top to bottom. Z is the depth, going straight into the screen.
\r
173 In this trainer, we are using lines, so we define 2 X,Y and Z
\r
174 coordinates, one for each end of the line. A line from far away, in the
\r
175 upper left of the X and Y axes, to close up in the bottom right of the
\r
176 X and Y axes, would look like this :
\r
178 { x1 y1 z1 x2 y2 z2 }
\r
179 ( (-10,10,-10),(10,-10,10) )
\r
182 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
183 þ Rotating a point with matrixes
\r
185 NOTE : I thought that more then one matix are matrisese (sp), but my
\r
186 spellchecker insists it is matrixes, so I let it have it's way
\r
189 Having a 3-D object is useless unless you can rotate it some way. For
\r
190 demonstration purposes, I will begin by working in two dimensions, X and
\r
193 Let us say you have a point, A,B, on a graph.
\r
195 | /O1 (Cos (a)*A-Sin (a)*B , Sin (a)*A+Cos (a)*B)
\r
201 Now, let us say we rotate this point by 45 degrees anti-clockwise. The
\r
202 new A,B can be easily be calculated using sin and cos, by an adaption of
\r
203 our circle algorithm, ie.
\r
204 A2:=Cos (45)*A - Sin (45)*B
\r
205 B2:=Sin (45)*A + Cos (45)*B
\r
206 I recall that in standard 8 and 9, we went rather heavily into this in
\r
207 maths. If you have troubles, fine a 8/9/10 maths book and have a look;
\r
208 it will go through the proofs etc.
\r
210 Anyway, we have now rotated an object in two dimensions, AROUND THE Z
\r
211 AXIS. In matrix form, the equation looks like this :
\r
213 [ Cos (a) -Sin (a) 0 0 ] [ x ]
\r
214 [ Sin (a) Cos (a) 0 0 ] . [ y ]
\r
218 I will not go to deeply into matrixes math at this stage, as there are
\r
219 many books on the subject (it is not part of matric maths, however). To
\r
220 multiply a matrix, to add the products of the row of the left matrix and
\r
221 the column of the right matrix, and repeat this for all the columns of the
\r
222 left matrix. I don't explain it as well as my first year maths lecturer,
\r
223 but have a look at how I derived A2 and B2 above. Here are the other
\r
226 Matrix for rotation around the Y axis :
\r
227 [ Cos (a) 0 -Sin (a) 0 ] [ x ]
\r
228 [ 0 1 0 0 ] . [ y ]
\r
229 [ Sin (a) 0 Cos (a) 0 ] [ z ]
\r
232 Matrix for rotation around the X axis :
\r
234 [ 0 Cos (a) -Sin (a) 0 ] . [ y ]
\r
235 [ 0 Sin (a) Cos (a) 0 ] [ z ]
\r
238 By putting all these matrixes together, we can translate out 3D points
\r
239 around the origin of 0,0,0. See the sample program for how we put them
\r
242 In the sample program, we have a constant, never changing base object.
\r
243 This is rotated into a second variable, which is then drawn. I am sure
\r
244 many of you can thing of cool ways to change the base object, the
\r
245 effects of which will appear while the object is rotating. One idea is
\r
246 to "pulsate" a certain point of the object according to the beat of the
\r
247 music being played in the background. Be creative. If you feel up to it,
\r
248 you could make your own version of transformers ;)
\r
252 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
253 þ Drawing a 3D point to screen
\r
255 Having a rotated 3D object is useless unless we can draw it to screen.
\r
256 But how do we show a 3D point on a 2D screen? The answer needs a bit of
\r
257 explaining. Examine the following diagram :
\r
259 | ________-------------
\r
260 ____|___------ o Object at X,Y,Z o1 Object at X,Y,Z2
\r
263 | -------------- Field of vision
\r
266 Let us pretend that the centre of the screen is the horizon of our
\r
267 little 3D world. If we draw a three dimensional line from object "o" to
\r
268 the centre of the eye, and place a pixel on the X and Y coordinates
\r
269 where it passes through the screen, we will notice that when we do the
\r
270 same with object o1, the pixel is closer to the horizon, even though
\r
271 their 3D X and Y coords are identical, but "o1"'s Z is larger then
\r
272 "o"'s. This means that the further away a point is, the closer to the
\r
273 horizon it is, or the smaller the object will appear. That sounds
\r
274 right, doesent it? But, I hear you cry, how do we translate this into a
\r
275 formula? The answer is quite simple. Divide your X and your Y by your Z.
\r
276 Think about it. The larger the number you divide by, the closer to zero,
\r
277 or the horizon, is the result! This means, the bigger the Z, the
\r
278 further away is the object! Here it is in equation form :
\r
280 nx := 256*x div (z-Zoff)+Xoff
\r
281 ny := 256*y div (z-Zoff)+Yoff
\r
283 NOTE : Zoff is how far away the entire object is, Xoff is the objects X
\r
284 value, and Yoff is the objects Y value. In the sample program,
\r
285 Xoff start off at 160 and Yoff starts off at 100, so that the
\r
286 object is in the middle of the screen.
\r
288 The 256 that you times by is the perspective with which you are viewing.
\r
289 Changing this value gives you a "fish eye" effect when viewing the
\r
290 object. Anyway, there you have it! Draw a pixel at nx,ny, and viola! you
\r
291 are now doing 3D! Easy, wasn't it?
\r
294 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
295 þ Possible improvements
\r
297 This program is not the most optimised routine you will ever encounter
\r
298 (;-)) ... it uses 12 muls and 2 divs per point. (Asphyxia currently has
\r
299 9 muls and 2 divs per point) Real math is used for all the calculations
\r
300 in the sample program, which is slow, so fixed point math should be
\r
301 implemented (I will cover fixed point math in a future trainer). The
\r
302 line routine currently being used is very slow. Chain-4 could be used to
\r
303 cut down on screen flipping times.
\r
305 Color values per line should be added, base object morphing could be put
\r
306 in, polygons could be used instead of lines, handling of more then one
\r
307 object should be implemented, clipping should be added instead of not
\r
308 drawing something if any part of it is out of bounds.
\r
310 In other words, you have a lot of work ahead of you ;)
\r
313 =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
\r
316 There are a lot of books out there on 3D, and quite a few sample
\r
317 programs too. Have a look at them, and use the best bits to create your
\r
318 own, unique 3D engine, with which you can do anything you want. I am
\r
319 very interested in 3D (though EzE and Goth wrote most of ASPHYXIA'S 3D
\r
320 routines), and would like to see what you can do with it. Leave me a
\r
321 message through one of the means described above.
\r
323 I am delving into the murky world of texture mapping. If anyone out
\r
324 there has some routines on the subject and are interested in swapping,
\r
327 What to do in future trainers? Help me out on this one! Are there any
\r
328 effects/areas you would like a bit of info on? Leave me a message!
\r
330 I unfortunately did not get any messages regarding BBS's that carry this
\r
331 series, so the list that follows is the same one from last time. Give
\r
332 me your names, sysops!
\r
334 Aaaaargh!!! Try as I might, I can't think of a new quote. Next time, I
\r
341 These fine BBS's carry the ASPHYXIA DEMO TRAINER SERIES : (alphabetical)
\r
343 ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍËÍÍÍÍÍËÍÍÍËÍÍÍÍËÍÍÍÍ»
\r
344 ºBBS Name ºTelephone No. ºOpen ºMsgºFileºPastº
\r
345 ÌÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÎÍÍÍÍÍÎÍÍÍÎÍÍÍÍÎÍÍÍ͹
\r
346 ºASPHYXIA BBS #1 º(031) 765-5312 ºALL º * º * º * º
\r
347 ºASPHYXIA BBS #2 º(031) 765-6293 ºALL º * º * º * º
\r
348 ºConnectix BBS º(031) 266-9992 ºALL º * º º º
\r
349 ºFor Your Eyes Only BBS º(031) 285-318 ºA/H º * º * º * º
\r
350 ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÊÍÍÍÍÍÊÍÍÍÊÍÍÍÍÊÍÍÍͼ
\r
352 Open = Open at all times or only A/H
\r
353 Msg = Available in message base
\r
354 File = Available in file base
\r
355 Past = Previous Parts available
\r
357 ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
\r
367 Obj : Array [1..MaxLines,1..2,1..3] of integer =
\r
369 ((-10,-10,-10),(10,-10,-10)),((-10,-10,-10),(-10,10,-10)),
\r
370 ((-10,10,-10),(10,10,-10)),((10,-10,-10),(10,10,-10)),
\r
371 ((-10,-10,10),(10,-10,10)),((-10,-10,10),(-10,10,10)),
\r
372 ((-10,10,10),(10,10,10)),((10,-10,10),(10,10,10)),
\r
373 ((-10,-10,10),(-10,-10,-10)),((-10,10,10),(-10,10,-10)),
\r
374 ((10,10,10),(10,10,-10)),((10,-10,10),(10,-10,-10))
\r
375 ); { The 3-D coordinates of our object ... stored as (X1,Y1,Z1), }
\r
376 { (X2,Y2,Z2) ... for the two ends of a line }
\r
379 Type Point = Record
\r
380 x,y,z:real; { The data on every point we rotate}
\r
382 Virtual = Array [1..64000] of byte; { The size of our Virtual Screen }
\r
383 VirtPtr = ^Virtual; { Pointer to the virtual screen }
\r
386 VAR Lines : Array [1..MaxLines,1..2] of Point; { The base object rotated }
\r
387 Translated : Array [1..MaxLines,1..2] of Point; { The rotated object }
\r
388 Xoff,Yoff,Zoff:Integer; { Used for movement of the object }
\r
389 lookup : Array [0..360,1..2] of real; { Our sin and cos lookup table }
\r
390 Virscr : VirtPtr; { Our first Virtual screen }
\r
391 Vaddr : word; { The segment of our virtual screen}
\r
394 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
395 Procedure SetMCGA; { This procedure gets you into 320x200x256 mode. }
\r
404 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
405 Procedure SetText; { This procedure returns you to text mode. }
\r
413 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
414 Procedure Cls (Where:word;Col : Byte);
\r
415 { This clears the screen to the specified color }
\r
429 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
430 Procedure SetUpVirtual;
\r
431 { This sets up the memory needed for the virtual screen }
\r
433 GetMem (VirScr,64000);
\r
434 vaddr := seg (virscr^);
\r
438 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
439 Procedure ShutDown;
\r
440 { This frees the memory used by the virtual screen }
\r
442 FreeMem (VirScr,64000);
\r
446 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
447 procedure flip(source,dest:Word);
\r
448 { This copies the entire screen at "source" to destination }
\r
465 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
466 Procedure Pal(Col,R,G,B : Byte);
\r
467 { This sets the Red, Green and Blue values of a certain color }
\r
484 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
485 Function rad (theta : real) : real;
\r
486 { This calculates the degrees of an angle }
\r
488 rad := theta * pi / 180
\r
492 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
493 Procedure SetUpPoints;
\r
494 { This sets the basic offsets of the object, creates the lookup table and
\r
495 moves the object from a constant to a variable }
\r
501 For loop1:=0 to 360 do BEGIN
\r
502 lookup [loop1,1]:=sin (rad (loop1));
\r
503 lookup [loop1,2]:=cos (rad (loop1));
\r
505 For loop1:=1 to MaxLines do BEGIN
\r
506 Lines [loop1,1].x:=Obj [loop1,1,1];
\r
507 Lines [loop1,1].y:=Obj [loop1,1,2];
\r
508 Lines [loop1,1].z:=Obj [loop1,1,3];
\r
509 Lines [loop1,2].x:=Obj [loop1,2,1];
\r
510 Lines [loop1,2].y:=Obj [loop1,2,2];
\r
511 Lines [loop1,2].z:=Obj [loop1,2,3];
\r
516 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
517 Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
\r
518 { This puts a pixel on the screen by writing directly to memory. }
\r
526 mov bx, dx {; bx = dx}
\r
529 add dx, bx {; dx = dx + bx (ie y*320)}
\r
530 add di, dx {; finalise location}
\r
538 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
539 Procedure Line(a,b,c,d:integer;col:byte;where:word);
\r
540 { This draws a solid line from a,b to c,d in colour col }
\r
541 function sgn(a:real):integer;
\r
543 if a>0 then sgn:=+1;
\r
544 if a<0 then sgn:=-1;
\r
545 if a=0 then sgn:=0;
\r
547 var i,s,d1x,d1y,d2x,d2y,u,v,m,n:integer;
\r
567 putpixel(a,b,col,where);
\r
584 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
585 Procedure DrawLogo;
\r
586 { This draws 'ASPHYXIA' at the top of the screen in little balls }
\r
587 CONST ball : Array [1..5,1..5] of byte =
\r
594 VAR Logo : Array [1..5] of String;
\r
595 loop1,loop2,loop3,loop4:integer;
\r
602 Logo[1]:=' O OOO OOO O O O O O O OOO O ';
\r
603 Logo[2]:='O O O O O O O O O O O O O O';
\r
604 Logo[3]:='OOO OOO OOO OOO O O O OOO';
\r
605 Logo[4]:='O O O O O O O O O O O O';
\r
606 Logo[5]:='O O OOO O O O O O O OOO O O';
\r
607 For loop1:=1 to 5 do
\r
608 For loop2:=1 to 31 do
\r
609 if logo[loop1][loop2]='O' then
\r
610 For loop3:=1 to 5 do
\r
611 For loop4:=1 to 5 do
\r
612 putpixel (loop2*10+loop3,loop1*4+loop4,ball[loop3,loop4],vaddr);
\r
617 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
618 Procedure RotatePoints (X,Y,Z:Integer);
\r
619 { This rotates object lines by X,Y and Z; then places the result in
\r
624 For loop1:=1 to maxlines do BEGIN
\r
625 temp.x:=lines[loop1,1].x;
\r
626 temp.y:=lookup[x,2]*lines[loop1,1].y - lookup[x,1]*lines[loop1,1].z;
\r
627 temp.z:=lookup[x,1]*lines[loop1,1].y + lookup[x,2]*lines[loop1,1].z;
\r
629 translated[loop1,1]:=temp;
\r
632 temp.x:=lookup[y,2]*translated[loop1,1].x - lookup[y,1]*translated[loop1,1].y;
\r
633 temp.y:=lookup[y,1]*translated[loop1,1].x + lookup[y,2]*translated[loop1,1].y;
\r
634 temp.z:=translated[loop1,1].z;
\r
635 translated[loop1,1]:=temp;
\r
639 temp.x:=lookup[z,2]*translated[loop1,1].x + lookup[z,1]*translated[loop1,1].z;
\r
640 temp.y:=translated[loop1,1].y;
\r
641 temp.z:=-lookup[z,1]*translated[loop1,1].x + lookup[z,2]*translated[loop1,1].z;
\r
642 translated[loop1,1]:=temp;
\r
645 temp.x:=lines[loop1,2].x;
\r
646 temp.y:=cos (rad(X))*lines[loop1,2].y - sin (rad(X))*lines[loop1,2].z;
\r
647 temp.z:=sin (rad(X))*lines[loop1,2].y + cos (rad(X))*lines[loop1,2].z;
\r
649 translated[loop1,2]:=temp;
\r
652 temp.x:=cos (rad(Y))*translated[loop1,2].x - sin (rad(Y))*translated[loop1,2].y;
\r
653 temp.y:=sin (rad(Y))*translated[loop1,2].x + cos (rad(Y))*translated[loop1,2].y;
\r
654 temp.z:=translated[loop1,2].z;
\r
655 translated[loop1,2]:=temp;
\r
659 temp.x:=cos (rad(Z))*translated[loop1,2].x + sin (rad(Z))*translated[loop1,2].z;
\r
660 temp.y:=translated[loop1,2].y;
\r
661 temp.z:=-sin (rad(Z))*translated[loop1,2].x + cos (rad(Z))*translated[loop1,2].z;
\r
662 translated[loop1,2]:=temp;
\r
669 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
670 Procedure DrawPoints;
\r
671 { This draws the translated object to the virtual screen }
\r
673 nx,ny,nx2,ny2:integer;
\r
676 For loop1:=1 to MaxLines do BEGIN
\r
677 If (translated[loop1,1].z+zoff<0) and (translated[loop1,2].z+zoff<0) then BEGIN
\r
678 temp:=round (translated[loop1,1].z+zoff);
\r
679 nx :=round (256*translated[loop1,1].X) div temp+xoff;
\r
680 ny :=round (256*translated[loop1,1].Y) div temp+yoff;
\r
681 temp:=round (translated[loop1,2].z+zoff);
\r
682 nx2:=round (256*translated[loop1,2].X) div temp+xoff;
\r
683 ny2:=round (256*translated[loop1,2].Y) div temp+yoff;
\r
684 If (NX > 0) and (NX < 320) and (NY > 25) and (NY < 200) and
\r
685 (NX2> 0) and (NX2< 320) and (NY2> 25) and (NY2< 200) then
\r
686 line (nx,ny,nx2,ny2,13,vaddr);
\r
691 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
692 Procedure ClearPoints;
\r
693 { This clears the translated object from the virtual screen ... believe it
\r
694 or not, this is faster then a straight "cls (vaddr,0)" }
\r
696 nx,ny,nx2,ny2:Integer;
\r
699 For loop1:=1 to MaxLines do BEGIN
\r
700 If (translated[loop1,1].z+zoff<0) and (translated[loop1,2].z+zoff<0) then BEGIN
\r
701 temp:=round (translated[loop1,1].z+zoff);
\r
702 nx :=round (256*translated[loop1,1].X) div temp+xoff;
\r
703 ny :=round (256*translated[loop1,1].Y) div temp+yoff;
\r
704 temp:=round (translated[loop1,2].z+zoff);
\r
705 nx2:=round (256*translated[loop1,2].X) div temp+xoff;
\r
706 ny2:=round (256*translated[loop1,2].Y) div temp+yoff;
\r
707 If (NX > 0) and (NX < 320) and (NY > 25) and (NY < 200) and
\r
708 (NX2> 0) and (NX2< 320) and (NY2> 25) and (NY2< 200) then
\r
709 line (nx,ny,nx2,ny2,0,vaddr);
\r
715 {ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ}
\r
716 Procedure MoveAround;
\r
717 { This is the main display procedure. Firstly it brings the object towards
\r
718 the viewer by increasing the Zoff, then passes control to the user }
\r
719 VAR deg,loop1:integer;
\r
726 For loop1:=-256 to -40 do BEGIN
\r
728 RotatePoints (deg,deg,deg);
\r
732 deg:=(deg+5) mod 360;
\r
736 if keypressed then BEGIN
\r
737 ch:=upcase (Readkey);
\r
738 Case ch of 'A' : zoff:=zoff+5;
\r
739 'Z' : zoff:=zoff-5;
\r
740 ',' : xoff:=xoff-5;
\r
741 '.' : xoff:=xoff+5;
\r
742 'S' : yoff:=yoff-5;
\r
743 'X' : yoff:=yoff+5;
\r
749 RotatePoints (deg,deg,deg);
\r
750 deg:=(deg+5) mod 360;
\r
757 Writeln ('Greetings and salutations! Hope you had a great Christmas and New');
\r
758 Writeln ('year! ;-) ... Anyway, this tutorial is on 3-D, so this is what is');
\r
759 Writeln ('going to happen ... a wireframe square will come towards you.');
\r
760 Writeln ('When it gets close, you get control. "A" and "Z" control the Z');
\r
761 Writeln ('movement, "," and "." control the X movement, and "S" and "X"');
\r
762 Writeln ('control the Y movement. I have not included rotation control, but');
\r
763 Writeln ('it should be easy enough to put in yourself ... if you have any');
\r
764 Writeln ('hassles, leave me mail.');
\r
766 Writeln ('Read the main text file for ideas on improving this code ... and');
\r
767 Writeln ('welcome to the world of 3-D!');
\r
770 Write (' Hit any key to contine ...');
\r
777 Writeln ('All done. This concludes the eigth sample program in the ASPHYXIA');
\r
778 Writeln ('Training series. You may reach DENTHOR under the names of GRANT');
\r
779 Writeln ('SMITH/DENTHOR/ASPHYXIA on the ASPHYXIA BBS. I am also an avid');
\r
780 Writeln ('Connectix BBS user, and occasionally read RSAProg.');
\r
781 Writeln ('For discussion purposes, I am also the moderator of the Programming');
\r
782 Writeln ('newsgroup on the For Your Eyes Only BBS.');
\r
783 Writeln ('The numbers are available in the main text. You may also write to me at:');
\r
784 Writeln (' Grant Smith');
\r
785 Writeln (' P.O. Box 270');
\r
786 Writeln (' Kloof');
\r
788 Writeln ('I hope to hear from you soon!');
\r
790 Write ('Hit any key to exit ...');
\r