home *** CD-ROM | disk | FTP | other *** search
/ C!T ROM 2 / ctrom_ii_b.zip / ctrom_ii_b / PROGRAM / PASCAL / 3DLIB20 / RTOBJ.PAS < prev    next >
Pascal/Delphi Source File  |  1993-06-03  |  38KB  |  915 lines

  1. (******************************************************************************
  2. *                                    rtObj                                    *
  3. *      please notice -                                                        *
  4. *      this unit includes both the object3d unit, and the superobj unit,      *
  5. *      and it is used with no reference to the WWToolKit window GUI library,  *
  6. *      uses project3, instead of prjWind  (It does, however, support OWL)     *
  7. *                                                                             *
  8. * In V2.x - The support collections are part of this unit as well ...         *
  9. ******************************************************************************)
  10. Unit rtObj;
  11.  
  12. (*******************************************************************************
  13. *                                 3D Objects                                   *
  14. *                                 ----------                                   *
  15. *                                                                              *
  16. *   A 3D object is a collection of points and lines in the 3D universe,        *
  17. *   that represent the body we want to draw on the screen.                     *
  18. *   A 3D object is allways centered around point (0, 0, 0) in the 3D universe. *
  19. *   (Its center of gravity assuming it is has a uniform weight distribution    *
  20. *    is in point (0, 0, 0)                                                     *
  21. *   At any moment during the object's life, we know it's distance from the     *
  22. *   origin, And it's rotation using reveres rotation CTM.                      *
  23. *                                                                              *
  24. *   3D Object methods:                                                         *
  25. *      constructor Open                                                        *
  26. *      destructor  CloseMe                                                     *
  27. *      procedures: Rotate, Scale, Move, Show, Hide, Load, Save                 *
  28. *                  SetToOrigin, Paint                                          *
  29. *                                                                              *
  30. *******************************************************************************)
  31.  
  32. interface
  33.  
  34. uses
  35. {$ifdef windows}
  36.     winTypes
  37.     ,winProcs
  38. {$else}
  39.     graph
  40. {$endif}
  41.     ,Ctm3d
  42.     ,hdr3d
  43.     ,project3
  44.     ,objects { needed for collection support .. }
  45.     ;
  46.  
  47. type
  48.    P3dPointCollection = ^ T3dPointCollection;
  49.    T3dPointCollection = object(TCollection)
  50.  
  51.       procedure freeItem(item : pointer); virtual;
  52.  
  53.    end; { T3dPointCollection definition .. }
  54.  
  55.    P3dLineCollection = ^ T3dLineCollection;
  56.    T3dLineCollection = object(TCollection)
  57.  
  58.       procedure freeItem(item : pointer); virtual;
  59.  
  60.    end; { T3dLineCollection definition .. }
  61.  
  62.    PScreenPointsCollection = ^ TScreenPointsCollection;
  63.    TScreenPointsCollection = object(TCollection)
  64.  
  65.       procedure freeItem(item : pointer); virtual;
  66.  
  67.    end; { TScreenPointsCollection definition .. }
  68.  
  69. type
  70.     f_real = file of real;
  71.  
  72.     {===================================================================}
  73.     {  Base object is the base class for 3D-objects. some functions     }
  74.     { are dummy virtual do-nothing, which are are implemented only for  }
  75.     { the descendend objects derived from BaseObject                    }
  76.     {===================================================================}
  77.  
  78.     BaseObjectPtr = ^BaseObject;
  79.     BaseObject = object
  80.        MyCtm       : Ctm;      { This CTM applied to the object gives the  }
  81.                                {  objects Position after transformations   }
  82.        Name        : String;   { Identifies the object                     }
  83.        myColor     : word;     { Main color for the object                 }
  84.        Location    : point3d;  { Central of gravity in real space          }
  85.        scrPntUpdt  : boolean;  { True if screen points updated             }
  86.  
  87.        constructor open(myName : string; color : word);
  88.        destructor  CloseMe; virtual;
  89. {$ifdef windows}
  90.        procedure   show(dc : hdc); virtual;
  91.        procedure   hide(dc : hdc); virtual;
  92.        procedure   paint(dc : hdc); virtual; {in specified color}
  93. {$else}
  94.        procedure   show; virtual;
  95.        procedure   hide; virtual;
  96.        procedure   paint; virtual; {in specified color}
  97. {$endif}
  98.        procedure   updateScreenPoints; virtual; {transform object 3D -> 2D}
  99.        procedure   move(axis : axisType; by : real); virtual;
  100.        procedure   translate(dx, dy, dz : integer); virtual;
  101.                {multy dimentional move in 1 call}
  102.        procedure   scale(axis : axisType; factor : real); virtual;
  103.        procedure   allScale(sx, sy, sz : real); virtual;
  104.                {multy dimentional scale in 1 call}
  105.        procedure   rotate(axis : axisType; deg : real); virtual;
  106.  
  107.        procedure   goto3dPos(x, y, z : real); virtual; {translate to absolute place}
  108.        procedure   setToOrigin; virtual;
  109.                {translate to 0,0,0, update points, and set myCtm to unit}
  110.        procedure   calcLocation; virtual; {set Location to central gravity}
  111.        procedure   deleteTransform; virtual; {set MyCtm to unit}
  112.  
  113.        function load : word; virtual; {from disk}
  114.        function save : word; virtual; {to   disk}
  115.        procedure writeMe(var elementFile : f_real); virtual; {to disk .. without opening file..}
  116.        procedure readMe(var elementFile : f_real); virtual;
  117.     end;
  118.  
  119.     {===================================================================}
  120.     { Obj3d is an object which represents a 3-D object with a poligon  }
  121.     {  mesh.                                                           }
  122.     {===================================================================}
  123.  
  124.     Obj3dPtr = ^Obj3d;
  125.     Obj3d = object(BaseObject)
  126. (*       Points      : array[1..MaxPoints] of point3d; *)
  127.        Points      : T3dPointCollection; 
  128. (*       Lines       : array[1..MaxLines]   of Line3d; *)
  129.        Lines       : T3dLineCollection;
  130. (*       scrPoints   : array[1..MaxPoints] of screenPoints; *)
  131.        scrPoints   : TScreenPointsCollection;
  132.        NumOfLines  : integer;
  133.        NumOfPoints : integer;
  134.        ReverseRot  : Ctm;  { Saves only the reverse rotations }
  135.        unReverseRot: Ctm;  { reverse of the above}
  136.  
  137.        constructor open(myName : string; ref : point3d; color : word);
  138.        destructor  CloseMe; virtual;
  139. {$ifdef windows}
  140.        procedure   paint(dc : hdc); virtual; {in specified color}
  141. {$else}
  142.        procedure   paint; virtual; {in specified color}
  143. {$endif}
  144.        procedure   updateScreenPoints; virtual; {transform object 3D -> 2D}
  145.  
  146.        procedure   calcLocation; virtual; {set Location to central gravity}
  147.        procedure   setToOrigin; virtual;
  148.  
  149.        procedure writeMe(var elementFile : f_real); virtual;
  150.        procedure readMe(var elementFile : f_real); virtual;
  151.     end;
  152.  
  153. const
  154.    maxSubObjects = 15;
  155.  
  156. type
  157.     complexObjPtr = ^complexObj;
  158.     ComplexObj = object(BaseObject)
  159.        childs      : array [1..maxSubObjects] of obj3dPtr;
  160.        ctms        : array [1..maxSubObjects] of ctm;
  161.        numOfChilds : integer; {counter of # of obj3d childs}
  162.  
  163.        constructor open(myName : string; color : word);
  164.        destructor  closeMe; virtual;
  165.        procedure   updateScreenPoints; virtual;
  166.        procedure   writeMe(var elementFile : f_real); virtual;
  167.        procedure   readMe(var elementFile : f_real); virtual;
  168.        procedure   calcLocation; virtual;
  169. {$ifdef WINDOWS}
  170.        procedure   paint(dc : hdc); virtual;
  171. {$else}
  172.        procedure   paint; virtual;
  173. {$endif}
  174.        procedure   move(axis : axisType; by : real); virtual;
  175.        procedure   rotate(axis : axisType; deg : real); virtual;
  176.        procedure   scale(axis : axisType; factor : real); virtual;
  177.  
  178.        function    addSubObject(myName : string; refPoint : point3d) : word;
  179.        function    getChildPtr(index : integer) : obj3dPtr;
  180.        procedure   rotateChild(child : integer; axis : axisType;
  181.                                        deg : real);
  182.        procedure   scaleChild(child : integer; axis : axisType;
  183.                                        factor : real);
  184.        procedure   moveChild(child : integer; axis : axisType;
  185.                                by : real);
  186.     end;
  187.  
  188.  
  189. implementation
  190.  
  191. (******************************************************************************
  192. *                         Collection-implementations                          *
  193. ******************************************************************************)
  194.  
  195. (******************************************************************************
  196. *                         T3dPointCollection.freeItem                         *
  197. ******************************************************************************)
  198. procedure T3dPointCollection.freeItem;
  199. begin
  200.    if (item <> nil) then
  201.       dispose(point3dPtr(item));
  202. end; {T3dPointCollection.freeItem}
  203.  
  204. (******************************************************************************
  205. *                         T3dLineCollection.freeItem                          *
  206. ******************************************************************************)
  207. procedure T3dLineCollection.freeItem;
  208. begin
  209.    if (item <> nil) then
  210.       dispose(line3dPtr(item));
  211. end; {T3dLineCollection.freeItem}
  212.  
  213. (******************************************************************************
  214. *                      TScreenPointsCollection.freeItem                       *
  215. ******************************************************************************)
  216. procedure TScreenPointsCollection.freeItem;
  217. begin
  218.    if (item <> nil) then
  219.       dispose(screenPointsPtr(item));
  220. end; {TScreenPointsCollection.freeItem}
  221.  
  222.     {%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%}
  223.     {                     BaseObject implementation                        }
  224.     {%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%}
  225.  
  226. (*******************************************************************************
  227. *                              BaseObject.Open                                 *
  228. *******************************************************************************)
  229. constructor BaseObject.Open;
  230. begin
  231.     name      := myName;
  232.     myColor   := color;
  233.     location  := ZeroPoint;
  234.     MyCtm.SetUnit;
  235. end; {baseObject.open}
  236.  
  237. (*******************************************************************************
  238. *                             BaseObject.CloseMe                               *
  239. *******************************************************************************)
  240. destructor BaseObject.CloseMe;
  241. begin
  242.     { I'm here so my children will Close-themselfs properly }
  243. end; {baseObject.closeMe}
  244.  
  245. (*******************************************************************************
  246. *                              BaseObject.move                                 *
  247. *******************************************************************************)
  248. procedure BaseObject.move(axis : axisType; by: real);
  249. begin
  250.        case axis of
  251.                x : begin
  252.                        myCtm.translateX(by);
  253.                        location.x :=location.x+by;
  254.                    end;
  255.                y : begin
  256.                        myCtm.translateY(by);
  257.                        location.y :=location.y+by;
  258.                    end;
  259.                z : begin
  260.                        myCtm.translateZ(by);
  261.                        location.z :=location.z+by;
  262.                    end;
  263.        end; {case}
  264.        scrPntUpdt := False;
  265. end; {BaseObject.move}
  266.  
  267. (*******************************************************************************
  268. *                            BaseObject.translate                              *
  269. *******************************************************************************)
  270. procedure BaseObject.translate(dx, dy, dz : integer);
  271. begin
  272.        myCtm.translate(dx,dy,dz);
  273.        location.x :=location.x+dx;
  274.        location.y :=location.y+dy;
  275.        location.z :=location.z+dz;
  276.        scrPntUpdt := False;
  277. end; {BaseObject.translate}
  278.  
  279. {use this routine when you know you need to translate more then one axis
  280.        before painting, you will use only one call, which will probably be
  281.        faster, and make your program easier to read, and maintain}
  282.  
  283. (*******************************************************************************
  284. *                              BaseObject.show                                 *
  285. *******************************************************************************)
  286. procedure BaseObject.show;
  287. {$ifdef windows}
  288. var
  289.    myPen, oldPen : HPen;
  290. {$endif}
  291. begin
  292. {$ifdef WINDOWS}
  293.     myPen := getStockObject(black_Pen);
  294.     oldPen := selectObject(dc, myPen);
  295.     paint(dc);
  296.     selectObject(dc, oldPen);
  297.     deleteObject(myPen);
  298. {$else}
  299.     setColor(myColor);
  300.     paint;
  301. {$endif}
  302. end; {baseObject.show}
  303.  
  304. (*******************************************************************************
  305. *                              BaseObject.hide                                 *
  306. *******************************************************************************)
  307. procedure BaseObject.hide;
  308. {$ifdef windows}
  309. var
  310.    myPen, oldPen : HPen;
  311. {$endif}
  312. begin
  313. {$ifdef windows}
  314.     myPen := getStockObject(white_Pen);
  315.     oldPen := selectObject(dc, myPen);
  316.     paint(dc);      {at this color}
  317.     selectObject(dc, oldPen);
  318.     deleteObject(myPen);
  319. {$else}
  320.     setColor(0); {backGround}
  321.     paint;      {at this color}
  322. {$endif}
  323. end; {baseObject.hide}
  324.  
  325. (*******************************************************************************
  326. *                              BaseObject.Paint                                *
  327. *******************************************************************************)
  328. procedure BaseObject.Paint;
  329. begin
  330.     if (not(scrPntUpdt)) then
  331.        updateScreenPoints;
  332.     { alas,  BaseObject cannot really paint becuase it does not have   }
  333.     { screen points (what a shame ...)                                 }
  334. end; {baseObject.paint}
  335.  
  336. (*******************************************************************************
  337. *                       BaseObject.UpdateScreenPoints                          *
  338. *******************************************************************************)
  339. procedure BaseObject.UpdateScreenPoints;
  340. begin
  341.     scrPntUpdt := True; { Have no screen points or any other points, so     }
  342.                         { points are already updated (I think)              }
  343. end; {updateScreenPoints}
  344.  
  345. (*******************************************************************************
  346. *                              BaseObject.scale                                *
  347. *******************************************************************************)
  348. procedure BaseObject.scale(axis : axisType; factor : real);
  349. begin
  350.        myCtm.translate(-location.x,-location.y,-location.z);
  351.        case axis of
  352.                x : myCtm.scaleX(factor);
  353.                y : myCtm.scaleY(factor);
  354.                z : myCtm.scaleZ(factor);
  355.        end; {scale}
  356.        myCtm.translate(location.x,location.y,location.z);
  357.        scrPntUpdt := False;
  358. end; {baseObject.scale}
  359.  
  360. (*******************************************************************************
  361. *                            BaseObject.allScale                               *
  362. *******************************************************************************)
  363. procedure BaseObject.allScale(sx,sy,sz : real);
  364. begin
  365.     myCtm.translate(-location.x, -location.y, -location.z);
  366.     myCtm.scale(sx,sy,sz);
  367.     myCtm.translate(location.x, location.y, location.z);
  368.     scrPntUpdt := False;
  369. end; {allScale}
  370. {call this routine to scale more then one axis at a time, with a single call}
  371.  
  372. (*******************************************************************************
  373. *                            BaseObject.goto3dPos                              *
  374. *******************************************************************************)
  375. procedure BaseObject.goto3dPos;
  376. begin
  377.        translate(round(x - location.x), round(y - location.y)
  378.                        , round(z - location.z));
  379. end; {baseObject.goto3dPos}
  380.  
  381. (*******************************************************************************
  382. *                           BaseObject.setToOrigin                             *
  383. *******************************************************************************)
  384. procedure BaseObject.setToOrigin;
  385. begin
  386.     goto3dPos(0, 0, 0);
  387.     myCtm.setUnit;
  388.     location := zeroPoint;
  389. end; {BaseObject.setToOrign}
  390.  
  391. (*******************************************************************************
  392. *                          BaseObject.CalcLocation                             *
  393. *******************************************************************************)
  394. procedure BaseObject.CalcLocation;
  395. begin
  396.     location := zeroPoint; { What else could it be when there are no points ?}
  397. end; {baseObject.calcLocation}
  398.  
  399. (*******************************************************************************
  400. *                         BaseObject.deleteTransform                           *
  401. *******************************************************************************)
  402. procedure BaseObject.deleteTransform;
  403. begin
  404.     myCtm.setUnit;
  405.     scrPntUpdt := false;
  406. end; {baseObject.deleteTransform}
  407.  
  408. (******************************************************************************
  409. *                              BaseObject.rotate                              *
  410. ******************************************************************************)
  411. procedure BaseObject.rotate;
  412. begin
  413.        myCtm.translate(-location.x,-location.y,-location.z);
  414.        case axis of
  415.                x :     myCtm.rotateX(deg);
  416.                y :     myCtm.rotateY(deg);
  417.                z :     myCtm.rotateZ(deg);
  418.        end; {case}
  419.        myCtm.translate(location.x,location.y,location.z);
  420.  
  421.        {rotation means : go to origin (translate -location),
  422.                          rotate       (rotate axis degrees),
  423.                          go to prev pos (translate location);
  424.        }
  425.  
  426.        scrPntUpdt := False;
  427. end; {BaseObject.rotate, see interface for comments}
  428.  
  429. (******************************************************************************
  430. *                               baseObject.load                               *
  431. ******************************************************************************)
  432. function baseObject.load;
  433. var
  434.     elementFile : f_real;
  435.     errC       : word;
  436. begin
  437.     {$i-} {supposed to be so, just making sure}
  438.     assign(elementFile,name);
  439.     reset(elementFile); {o.k. open it}
  440.     errC := ioResult;
  441.     load := errC;
  442.     if (errC = 0) then begin
  443.        readMe(elementFile);
  444.        errC := ioResult;
  445.        load := errC;
  446.        close(elementFile);
  447.        calcLocation;
  448.        scrPntUpdt := false;
  449.     end; {if}
  450. end; { baseObject.load}
  451.  
  452. (******************************************************************************
  453. *                               baseObject.save                               *
  454. ******************************************************************************)
  455. function baseObject.save;
  456. var
  457.     elementFile : f_real;
  458.     errC       : word;
  459. begin
  460.     {$i-} {supposed to be so, just making sure}
  461.     assign(elementFile,name);
  462.     rewrite(elementFile); {o.k. open it}
  463.     errC := ioResult;
  464.     save := errC;
  465.     if (errC = 0) then begin
  466.        writeMe(elementFile);
  467.        errC := ioResult; save := errC;
  468.        close(elementFile);
  469.     end; {if}
  470. end; {baseObject.save}
  471.  
  472. (******************************************************************************
  473. *                             baseObject.writeMe                              *
  474. ******************************************************************************)
  475. procedure baseObject.writeMe;
  476. begin
  477.    {override by descendents }
  478. end; {baseObject.writeMe}
  479.  
  480. (******************************************************************************
  481. *                              baseObject.readMe                              *
  482. ******************************************************************************)
  483. procedure baseObject.readMe;
  484. begin
  485.    {override by descendents }
  486. end; {baseObject.readMe}
  487.  
  488.     {%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%}
  489.     {                        Obj3d implementation                          }
  490.     {%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%}
  491.  
  492.  
  493. (*******************************************************************************
  494. *                                 Obj3d.open                                   *
  495. *******************************************************************************)
  496. constructor Obj3d.open;
  497. begin
  498.     BaseObject.Open(myName, color);
  499.     scrPntUpdt := False; {not calculated yet}
  500.     numOfLines := 0;
  501.     numOfPoints := 0;
  502.     myCtm.setUnit; {initialize to unit matrix}
  503.     reverseRot.setUnit;
  504.     unReverseRot.setUnit;
  505.     points.init(maxPoints, 5);
  506.     lines.init(maxLines, 5);
  507.     scrPoints.init(maxPoints, 5); { initiailize collections .. }
  508. end; {Obj3d.open}
  509.  
  510. (*******************************************************************************
  511. *                               Obj3d.CloseMe                                  *
  512. *******************************************************************************)
  513. destructor Obj3d.CloseMe;
  514. begin
  515. end;  {Obj3d.Close}
  516.  
  517.  
  518. (*******************************************************************************
  519. *                          Obj3d.updateScreenPoints                            *
  520. *******************************************************************************)
  521. procedure Obj3d.updateScreenPoints;
  522. var i : integer;
  523.     p : point3d;
  524. begin
  525.     for i := 1 to numOfPoints do begin
  526.        myCtm.transform(p, point3dPtr(points.items^[i])^); {transform by ctm}
  527.        calcPoint(p, screenPointsPtr(scrPoints.items^[i])^);
  528.     end; {for}
  529.     scrPntUpdt := True; {make sure for next time..}
  530.            {make all points ready}
  531. end; {obj3d.updateScreenPoints}
  532.  
  533. (*******************************************************************************
  534. *                                Obj3d.paint                                   *
  535. *******************************************************************************)
  536. procedure Obj3d.paint;
  537. {do the actual painting here}
  538. var
  539.     i : integer;
  540. begin
  541.     if ((numOfPoints = 0) or (numOfLines = 0)) then exit;
  542.     if (not(scrPntUpdt)) then
  543.        updateScreenPoints;
  544.     for i := 1 to numOfLines do begin
  545. {$ifdef windows}
  546.        moveTo(dc, screenPointsPtr(scrPoints.items^[line3dPtr(lines.items^[i])^.fromP])^.sX, 
  547.                   screenPointsPtr(scrPoints.items^[line3dPtr(lines.items^[i])^.fromP])^.sY);
  548.        lineTo(dc, screenPointsPtr(scrPoints.items^[line3dPtr(lines.items^[i])^.toP])^.sX, 
  549.                   screenPointsPtr(scrPoints.items^[line3dPtr(lines.items^[i])^.toP])^.sY  );
  550. {$else}
  551.        line(screenPointsPtr(scrPoints.items^[line3dPtr(lines.items^[i])^.fromP])^.sX,
  552.             screenPointsPtr(scrPoints.items^[line3dPtr(lines.items^[i])^.fromP])^.sY,
  553.             screenPointsPtr(scrPoints.items^[line3dPtr(lines.items^[i])^.toP])^.sX,
  554.             screenPointsPtr(scrPoints.items^[line3dPtr(lines.items^[i])^.toP])^.sY);
  555. {$endif}
  556.     end; { for }
  557.     {it should be noted that calcPoint has to convert points to integers}
  558. end; {obj3d.paint}
  559.  
  560. (******************************************************************************
  561. *                                obj3d.readMe                                 *
  562. ******************************************************************************)
  563. procedure obj3d.readMe;
  564. var
  565.     tmp1,tmp2  : real;
  566.     i,j        : byte;
  567.     p          : point3dPtr;
  568.     l          : line3dPtr;
  569.     s          : screenPointsPtr;
  570. begin
  571.        new(p);
  572.        points.insert(p); { we hold one un-used entry - because collection
  573.                            index is 0, and out is 1, so instead of calculating
  574.                            all of these -1's, we kill some space .. }
  575.        new(s);
  576.        scrPoints.insert(s);
  577.        new(l);
  578.        lines.insert(l);
  579.  
  580.        read(elementFile, tmp1);
  581.        numOfPoints := trunc(tmp1);
  582.        for j := 1 to numOfPoints do begin
  583.            new(p);
  584.            read(elementFile, p^.x);
  585.            read(elementFile, p^.y);
  586.            read(elementFile, p^.z);
  587.            points.insert(p);
  588.            new(s);
  589.            scrPoints.insert(s); { allocate place for screen points .. }
  590.        end; {for}
  591.        read(elementFile, tmp1);
  592.        numOfLines := trunc(tmp1);
  593.        for j := 1 to numOfLines do begin
  594.            new(l);
  595.            read(elementFile, tmp1, tmp2);
  596.            l^.fromP := trunc(tmp1);
  597.            l^.toP   := trunc(tmp2);
  598.            lines.insert(l);
  599.        end; {for}
  600. end; {obj3d.readMe}
  601.  
  602. (******************************************************************************
  603. *                                obj3d.writeMe                                *
  604. ******************************************************************************)
  605. procedure obj3d.writeMe;
  606. var
  607.     tmp1,tmp2  : real;
  608.     i,j        : byte;
  609. begin
  610.        tmp1 := numOfPoints;
  611.        write(elementFile, tmp1);
  612.        for j := 1 to numOfPoints do with point3dPtr(points.items^[j])^ do begin
  613.            write(elementFile, x);
  614.            write(elementFile, y);
  615.            write(elementFile, z);
  616.        end; {for}
  617.        tmp1 := numOfLines;
  618.        write(elementFile, tmp1);
  619.        for j := 1 to numOfLines do with line3dPtr(lines.items^[j])^ do begin
  620.            tmp1 := fromP;
  621.            tmp2 := toP;
  622.            write(elementFile, tmp1, tmp2);
  623.        end;
  624. end; {obj3d.writeMe}
  625.  
  626. (*******************************************************************************
  627. *                             obj3d.calcLocation                               *
  628. *******************************************************************************)
  629. procedure obj3d.calcLocation;
  630. var
  631.        ce : point3d;
  632.        p  : point3d;
  633.        i  : integer;
  634. begin
  635.        ce := zeroPoint; { (0, 0, 0) -> ce }
  636.        for i := 1 to numOfPoints do begin
  637.                myCtm.transform(p, point3dPtr(points.items^[i])^);
  638.                ce.x := ce.x + p.x;
  639.                ce.y := ce.y + p.y;
  640.                ce.z := ce.z + p.z;
  641.        end; {for}
  642.        location.x := ce.x / numOfPoints;
  643.        location.y := ce.y / numOfPoints;
  644.        location.z := ce.z / numOfPoints;
  645. end; {obj3d.calcLocation}
  646.  
  647. (*******************************************************************************
  648. *                             Obj3d.setToOrigin                                *
  649. *******************************************************************************)
  650. procedure Obj3d.setToOrigin;
  651. var
  652.        i : integer;
  653.        p : point3d;
  654. begin
  655.     goto3dPos(0, 0, 0);
  656.     for i := 1 to numOfPoints do begin
  657.            myCtm.transform(p, point3dPtr(points.items^[i])^);
  658.            point3dPtr(points.items^[i])^ := p;
  659.     end; {for}
  660.     scrPntUpdt := False; (** Instead of that THING above **)
  661.     myCtm.setUnit;
  662.     location := zeroPoint;
  663. end; {BaseObject.setToOrign}
  664.  
  665. (*******************************************************************************
  666. *                              ComplexObj.Open                                 *
  667. *******************************************************************************)
  668. constructor ComplexObj.Open;
  669. begin
  670.     BaseObject.Open(myName, color);
  671.     numOfChilds := 0;
  672. end; {complexObj.open}
  673.  
  674. (*******************************************************************************
  675. *                             ComplexObj.CloseMe                               *
  676. *******************************************************************************)
  677. destructor ComplexObj.CloseMe;
  678. var
  679.        i : integer;
  680.  
  681. begin
  682.        for i := 1 to numOfChilds do
  683.                dispose(childs[i],closeMe);
  684.        baseObject.closeMe;
  685. end; {complexObj.closeMe}
  686.  
  687. (*******************************************************************************
  688. *                          ComplexObj.addSubObject                             *
  689. *******************************************************************************)
  690. function ComplexObj.addSubObject;
  691. var
  692.     ret_code : word;
  693. begin
  694.        if (numOfChilds >= maxSubObjects) then begin
  695.                addSubObject := 255; {signal error}
  696.                exit;
  697.        end;
  698.        inc(numOfChilds);
  699.        childs[numOfChilds] := new(obj3dPtr, open(myName, zeroPoint, myColor));
  700.        ret_code := childs[numOfChilds]^.load;
  701.        if (ret_code = 0) then begin
  702.                with refPoint do
  703.                        childs[numOfChilds]^.translate(round(x),
  704.                                                round(y), round(z));
  705.                ctms[numOfChilds].copy(childs[numOfChilds]^.myCtm);
  706.        end; {if ret_c..}
  707.        addSubObject := ret_code;
  708. end; {complexObj.addSubObject}
  709.  
  710. (*******************************************************************************
  711. *                       complexObj.updateScreenPoints                          * 
  712. *******************************************************************************)
  713. procedure complexObj.updateScreenPoints;
  714. var
  715.     i : integer;
  716. begin
  717.     for i := 1 to numOfChilds do begin
  718.        childs[i]^.myCtm.multiply_2(ctms[i], myCtm);
  719.        childs[i]^.updateScreenPoints;
  720.     end;
  721.     scrPntUpdt := True;
  722. end; {complexObj.updateScreenPoints}
  723.  
  724. (*******************************************************************************
  725. *                           complexObj.getChildPtr                             *
  726. *******************************************************************************)
  727. function complexObj.getChildPtr;
  728. begin
  729.        getChildPtr := childs[index];
  730. end; {complexObj.getChildPtr}
  731.  
  732. (*******************************************************************************
  733. *                           ComplexObj.rotateChild                             *
  734. *******************************************************************************)
  735. procedure ComplexObj.rotateChild;
  736. begin
  737.     with childs[child]^ do begin
  738.        myCtm.copy(ctms[child]);
  739.        rotate(axis, deg);
  740.        ctms[Child].copy(MyCtm);
  741.        myCtm.Multiply(Self.myCtm);
  742.     end;
  743. end; {complexObj.rotateChild}
  744.  
  745. (*******************************************************************************
  746. *                           ComplexObj.scaleChild                              *
  747. *******************************************************************************)
  748. procedure ComplexObj.scaleChild;
  749. begin
  750.     with childs[child]^ do begin
  751.        myCtm.copy(ctms[child]);
  752.        scale(axis, factor);
  753.        ctms[Child].copy(MyCtm);
  754.        myCtm.Multiply(Self.myCtm);
  755.     end;
  756. end; {complexObj.scaleChild}
  757.  
  758. (*******************************************************************************
  759. *                            ComplexObj.moveChild                              *
  760. *******************************************************************************)
  761. procedure ComplexObj.moveChild;
  762. begin
  763.     with childs[child]^ do begin
  764.        myCtm.copy(ctms[child]);
  765.        move(axis, by);
  766.        ctms[Child].copy(MyCtm);
  767.        myCtm.Multiply(Self.myCtm);
  768.     end;
  769. end; {complexObj.moveChild}
  770.  
  771. (******************************************************************************
  772. *                              complexObj.paint                               *
  773. ******************************************************************************)
  774. procedure complexObj.paint;
  775. var
  776.        i : integer;
  777. begin
  778.     if (not(scrPntUpdt)) then
  779.        updateScreenPoints;
  780.     for i := 1 to numOfChilds do
  781. {$ifdef WINDOWS}
  782.        childs[i]^.paint(dc);
  783. {$else}
  784.        childs[i]^.paint;
  785. {$endif}
  786. end; {complexObj.paint}
  787.  
  788. (******************************************************************************
  789. *                             complexObj.writeMe                              *
  790. ******************************************************************************)
  791. procedure complexObj.writeMe;
  792. var
  793.        i : integer;
  794.        r : real;
  795. begin
  796.        r := 0.0 + numOfChilds;
  797.        write(elementFile, r);
  798.        for i := 1 to numOfChilds do
  799.                childs[i]^.writeMe(elementFile); {let all the kids write themselvs}
  800. end; {complexObj.writeMe}
  801.  
  802. (******************************************************************************
  803. *                              complexObj.readMe                              *
  804. ******************************************************************************)
  805. procedure complexObj.readMe;
  806. var
  807.        i : integer;
  808.        r : real;
  809. begin
  810.        read(elementFile, r);
  811.        numOfChilds := round(r);
  812.        for i := 1 to numOfChilds do begin
  813.               childs[i] := new(Obj3dPtr, Open('Child', ZeroPoint, myColor));
  814.               childs[i]^.readMe(elementFile);
  815.               childs[i]^.calcLocation;
  816.               ctms[i].setUnit;
  817.        end; {for}
  818. end; {complexObj.readMe}
  819.  
  820. (******************************************************************************
  821. *                           complexObj.calcLocation                           *
  822. ******************************************************************************)
  823. procedure complexObj.calcLocation;
  824. var
  825.        i : integer;
  826. begin
  827.        location := zeroPoint;
  828.        for i := 1 to numOfChilds do
  829.                with childs[i]^ do begin
  830.                        calcLocation;
  831.                        self.location.x := location.x + self.location.x;
  832.                        self.location.y := location.y + self.location.y;
  833.                        self.location.z := location.z + self.location.z;
  834.                end; {with}
  835.        with location do begin
  836.                x := x / numOfChilds;
  837.                y := y / numOfChilds;
  838.                z := z / numOfChilds;
  839.        end; {with..}
  840. end; {complexObj.calclocation}
  841.  
  842. (******************************************************************************
  843. *                               complexObj.move                               *
  844. ******************************************************************************)
  845. procedure complexObj.move;
  846. var
  847.        i : integer;
  848. begin
  849. (*       for i := 1 to numOfChilds do
  850.                with childs[i]^ do
  851.                        case axis of
  852.                                x : location.x := location.x + by;
  853.                                y : location.y := location.y + by;
  854.                                z : location.z := location.z + by;
  855.                        end; {case}  *)
  856.        baseObject.move(axis, by);
  857. end; {complexObj.move}
  858.  
  859. (******************************************************************************
  860. *                              complexObj.rotate                              *
  861. ******************************************************************************)
  862. procedure complexObj.rotate;
  863. var
  864.        i : integer;
  865.        sint, cost : real;
  866. begin
  867. (*       cost := cos(deg / 180.0 * 3.1415926535897932385);
  868.        sint := sin(deg / 180.0 * 3.1415926535897932385);
  869.        for i := 1 to numOfChilds do
  870.                with childs[i]^ do
  871.                        case axis of
  872.                                x : begin
  873.                                        location.y := location.y * cost -
  874.                                                location.z * sint;
  875.                                        location.z := location.y * sint +
  876.                                                location.z * cost;
  877.                                end; {x}
  878.                                y : begin
  879.                                        location.x := location.x * cost +
  880.                                                location.z * sint;
  881.                                        location.z := location.z * cost -
  882.                                                location.x * sint;
  883.                                end; {y}
  884.                                z : begin
  885.                                        location.x := location.x * cost -
  886.                                                location.y * sint;
  887.                                        location.y := location.y * cost +
  888.                                                location.x * sint;
  889.                                end; {z}
  890.                        end; {case} *)
  891.        baseObject.rotate(axis, deg);
  892. end; {complexObj.rotate}
  893.  
  894. (******************************************************************************
  895. *                              complexObj.scale                               *
  896. ******************************************************************************)
  897. procedure complexObj.scale;
  898. var
  899.        i : integer;
  900. begin
  901. (*       for i := 1 to numOfChilds do
  902.                with childs[i]^ do
  903.                        case axis of
  904.                                x : location.x := location.x * factor;
  905.                                y : location.y := location.y * factor;
  906.                                z : location.z := location.z * factor;
  907.                        end; {case} *)
  908.        baseObject.scale(axis, factor);
  909. end; {complexObj.scale}
  910.  
  911. (******************************************************************************
  912. *                                    end.                                     *
  913. ******************************************************************************)
  914. end.
  915.