home *** CD-ROM | disk | FTP | other *** search
- (******************************************************************************
- * rtObj *
- ******************************************************************************)
- Unit rtObj;
-
-
- (*
- please notice -
- this unit includes both the object3d unit, and the superobj unit,
- and it is used with no reference to the window GUI library,
- uses project3, instead of prjWind
- *)
-
- (*******************************************************************************
- * 3D Objects *
- * ---------- *
- * *
- * A 3D object is a collection of points and lines in the 3D universe, *
- * that represent the body we want to draw on the screen. *
- * A 3D object is allways centered around point (0, 0, 0) in the 3D universe. *
- * (Its center of gravity assuming it is has a uniform weight distribution *
- * is in point (0, 0, 0) *
- * At any moment during the object's life, we know it's distance from the *
- * origin, And it's rotation using reveres rotation CTM. *
- * *
- * 3D Object methods: *
- * constructor Open *
- * destructor CloseMe *
- * procedures: Rotate, Scale, Move, Show, Hide, Load, Save *
- * SetToOrigin, Paint *
- * *
- *******************************************************************************)
-
-
- interface
- uses
- Graph
- ,Ctm3d
- ,hdr3d
- ,project3
- ;
-
- type
-
- f_real = file of real;
-
- {===================================================================}
- { Base object is the base class for 3D-objects. some functions }
- { are dummy virtual do-nothing, which are are implemented only for }
- { the descendend objects derived from BaseObject }
- {===================================================================}
-
- BaseObjectPtr = ^BaseObject;
- BaseObject = object
- MyCtm : Ctm; { This CTM applied to the object gives the }
- { objects Position after transformations }
- Name : String; { Identifies the object }
- myColor : word; { Main color for the object }
- Location : point3d; { Central of gravity in real space }
- scrPntUpdt : boolean; { True if screen points updated }
-
- constructor open(myName : string; color : word);
- destructor CloseMe; virtual;
- procedure show; virtual;
- procedure hide; virtual;
- procedure paint; virtual; {in specified color}
- procedure updateScreenPoints; virtual; {transform object 3D -> 2D}
- procedure move(axis : axisType; by : real); virtual;
- procedure translate(dx, dy, dz : integer); virtual;
- {multy dimentional move in 1 call}
- procedure scale(axis : axisType; factor : real); virtual;
- procedure allScale(sx, sy, sz : real); virtual;
- {multy dimentional scale in 1 call}
- procedure rotate(axis : axisType; deg : real); virtual;
-
- procedure goto3dPos(x, y, z : real); virtual; {translate to absolute place}
- procedure setToOrigin; virtual;
- {translate to 0,0,0, update points, and set myCtm to unit}
- procedure calcLocation; virtual; {set Location to central gravity}
- procedure deleteTransform; virtual; {set MyCtm to unit}
-
- function load : word; virtual; {from disk}
- function save : word; virtual; {to disk}
- procedure writeMe(var elementFile : f_real); virtual; {to disk .. without opening file..}
- procedure readMe(var elementFile : f_real); virtual;
- end;
- {===================================================================}
- { Obj3d is an object which represents a 3-D object with a poligon }
- { mesh. }
- {===================================================================}
-
- Obj3dPtr = ^Obj3d;
- Obj3d = object(BaseObject)
- Points : array[1..MaxPoints] of point3d;
- Lines : array[1..MaxLines] of Line3d;
- scrPoints : array[1..MaxPoints] of screenPoints;
- NumOfLines : integer;
- NumOfPoints : integer;
- ReverseRot : Ctm; { Saves only the reverse rotations }
- unReverseRot: Ctm; { reverse of the above}
-
- constructor open(myName : string; ref : point3d; color : word);
- destructor CloseMe; virtual;
- procedure paint; virtual; {in specified color}
- procedure updateScreenPoints; virtual; {transform object 3D -> 2D}
-
- procedure calcLocation; virtual; {set Location to central gravity}
- procedure setToOrigin; virtual;
-
- procedure writeMe(var elementFile : f_real); virtual;
- procedure readMe(var elementFile : f_real); virtual;
- end;
-
- const
- maxSubObjects = 15;
-
- type
- complexObjPtr = ^complexObj;
- ComplexObj = object(BaseObject)
- childs : array [1..maxSubObjects] of obj3dPtr;
- ctms : array [1..maxSubObjects] of ctm;
- numOfChilds : integer; {counter of # of obj3d childs}
-
- constructor open(myName : string; color : word);
- destructor closeMe; virtual;
- procedure updateScreenPoints; virtual;
- procedure writeMe(var elementFile : f_real); virtual;
- procedure readMe(var elementFile : f_real); virtual;
- procedure calcLocation; virtual;
- procedure paint; virtual;
- procedure move(axis : axisType; by : real); virtual;
- procedure rotate(axis : axisType; deg : real); virtual;
- procedure scale(axis : axisType; factor : real); virtual;
-
- function addSubObject(myName : string; refPoint : point3d) : word;
- function getChildPtr(index : integer) : obj3dPtr;
- procedure rotateChild(child : integer; axis : axisType;
- deg : real);
- procedure scaleChild(child : integer; axis : axisType;
- factor : real);
- procedure moveChild(child : integer; axis : axisType;
- by : real);
- end;
-
-
- implementation
-
-
- {%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%}
- { BaseObject implementation }
- {%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%}
-
- (*******************************************************************************
- * BaseObject.Open *
- *******************************************************************************)
- constructor BaseObject.Open;
- begin
- name := myName;
- myColor := color;
- location := ZeroPoint;
- MyCtm.SetUnit;
- end;
-
- (*******************************************************************************
- * BaseObject.CloseMe *
- *******************************************************************************)
- destructor BaseObject.CloseMe;
- begin
- { I'm here so my children will Close-themselfs properly }
- end;
-
- (*******************************************************************************
- * BaseObject.move *
- *******************************************************************************)
- procedure BaseObject.move(axis : axisType; by: real);
- begin
- case axis of
- x : begin
- myCtm.translateX(by);
- location.x :=location.x+by;
- end;
- y : begin
- myCtm.translateY(by);
- location.y :=location.y+by;
- end;
- z : begin
- myCtm.translateZ(by);
- location.z :=location.z+by;
- end;
- end; {case}
- scrPntUpdt := False;
- end; {BaseObject.move}
-
- (*******************************************************************************
- * BaseObject.translate *
- *******************************************************************************)
- procedure BaseObject.translate(dx, dy, dz : integer);
- begin
- myCtm.translate(dx,dy,dz);
- location.x :=location.x+dx;
- location.y :=location.y+dy;
- location.z :=location.z+dz;
- scrPntUpdt := False;
- end; {BaseObject.translate}
-
- {use this routine when you know you need to translate more then one axis
- before painting, you will use only one call, which will probably be
- faster, and make your program easier to read, and maintain}
-
-
-
- (*******************************************************************************
- * BaseObject.show *
- *******************************************************************************)
- procedure BaseObject.show;
- begin
- setColor(myColor);
- paint;
- end;
-
- (*******************************************************************************
- * BaseObject.hide *
- *******************************************************************************)
- procedure BaseObject.hide;
- begin
- setColor(0); {backGround}
- paint; {at this color}
- end;
-
- (*******************************************************************************
- * BaseObject.Paint *
- *******************************************************************************)
- procedure BaseObject.Paint;
- begin
- if (not(scrPntUpdt)) then
- updateScreenPoints;
- { alas, BaseObject cannot really paint becuase it does not have }
- { screen points (what a shame ...) }
- end;
-
- (*******************************************************************************
- * BaseObject.UpdateScreenPoints *
- *******************************************************************************)
- procedure BaseObject.UpdateScreenPoints;
- begin
- scrPntUpdt := True; { Have no screen points or any other points, so }
- { points are already updated (I think) }
- end;
-
- (*******************************************************************************
- * BaseObject.scale *
- *******************************************************************************)
- procedure BaseObject.scale(axis : axisType; factor : real);
- begin
- myCtm.translate(-location.x,-location.y,-location.z);
- case axis of
- x : myCtm.scaleX(factor);
- y : myCtm.scaleY(factor);
- z : myCtm.scaleZ(factor);
- end; {scale}
- myCtm.translate(location.x,location.y,location.z);
- scrPntUpdt := False;
- end;
-
- (*******************************************************************************
- * BaseObject.allScale *
- *******************************************************************************)
- procedure BaseObject.allScale(sx,sy,sz : real);
- begin
- myCtm.translate(-location.x, -location.y, -location.z);
- myCtm.scale(sx,sy,sz);
- myCtm.translate(location.x, location.y, location.z);
- scrPntUpdt := False;
- end;
- {call this routine to scale more then one axis at a time, with a single call}
-
-
- (*******************************************************************************
- * BaseObject.goto3dPos *
- *******************************************************************************)
- procedure BaseObject.goto3dPos;
- begin
- translate(round(x - location.x), round(y - location.y)
- , round(z - location.z));
- end; {obj3d.goto3dPos}
-
- (*******************************************************************************
- * BaseObject.setToOrigin *
- *******************************************************************************)
- procedure BaseObject.setToOrigin;
- begin
- goto3dPos(0, 0, 0);
- myCtm.setUnit;
- location := zeroPoint;
- end; {BaseObject.setToOrign}
-
- (*******************************************************************************
- * BaseObject.CalcLocation *
- *******************************************************************************)
- procedure BaseObject.CalcLocation;
- begin
- location := zeroPoint; { What else could it be when there are no points ?}
- end;
-
- (*******************************************************************************
- * BaseObject.deleteTransform *
- *******************************************************************************)
- procedure BaseObject.deleteTransform;
- begin
- myCtm.setUnit;
- scrPntUpdt := false;
- end;
-
- (******************************************************************************
- * BaseObject.rotate *
- ******************************************************************************)
- procedure BaseObject.rotate;
- begin
- myCtm.translate(-location.x,-location.y,-location.z);
- case axis of
- x : myCtm.rotateX(deg);
- y : myCtm.rotateY(deg);
- z : myCtm.rotateZ(deg);
- end; {case}
- myCtm.translate(location.x,location.y,location.z);
-
- {rotation means : go to origin (translate -location),
- rotate (rotate axis degrees),
- go to prev pos (translate location);
- }
-
- scrPntUpdt := False;
- end; {BaseObject.rotate, see interface for comments}
-
- (******************************************************************************
- * baseObject.load *
- ******************************************************************************)
- function baseObject.load;
- var
- elementFile : f_real;
- errC : word;
- begin
- {$i-} {supposed to be so, just making sure}
- assign(elementFile,name);
- reset(elementFile); {o.k. open it}
- errC := ioResult;
- load := errC;
- if (errC = 0) then begin
- readMe(elementFile);
- errC := ioResult;
- load := errC;
- close(elementFile);
- calcLocation;
- scrPntUpdt := false;
- end; {if}
- end;
-
- (******************************************************************************
- * baseObject.save *
- ******************************************************************************)
- function baseObject.save;
- var
- elementFile : f_real;
- errC : word;
- begin
- {$i-} {supposed to be so, just making sure}
- assign(elementFile,name);
- rewrite(elementFile); {o.k. open it}
- errC := ioResult;
- save := errC;
- if (errC = 0) then begin
- writeMe(elementFile);
- errC := ioResult; save := errC;
- close(elementFile);
- end; {if}
- end;
-
- (******************************************************************************
- * baseObject.writeMe *
- ******************************************************************************)
- procedure baseObject.writeMe;
- begin
- end;
-
- (******************************************************************************
- * baseObject.readMe *
- ******************************************************************************)
- procedure baseObject.readMe;
- begin
- end;
-
- {%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%}
- { Obj3d implementation }
- {%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%}
-
-
- (*******************************************************************************
- * Obj3d.open *
- *******************************************************************************)
- constructor Obj3d.open;
- begin
- BaseObject.Open(myName, color);
- scrPntUpdt := False; {not calculated yet}
- numOfLines := 0;
- numOfPoints := 0;
- myCtm.setUnit; {initialize to unit matrix}
- reverseRot.setUnit;
- unReverseRot.setUnit;
- end; {Obj3d.open}
-
- (*******************************************************************************
- * Obj3d.CloseMe *
- *******************************************************************************)
- destructor Obj3d.CloseMe;
- begin
- end; {Obj3d.Close}
-
-
- (*******************************************************************************
- * Obj3d.updateScreenPoints *
- *******************************************************************************)
- procedure Obj3d.updateScreenPoints;
- var i : integer;
- p : point3d;
- begin
- for i := 1 to numOfPoints do begin
- myCtm.transform(p,points[i]); {transform by ctm}
- calcPoint(p, scrPoints[i]);
- end; {for}
- scrPntUpdt := True; {make sure for next time..}
- {make all points ready}
- end;
-
- (*******************************************************************************
- * Obj3d.paint *
- *******************************************************************************)
- procedure Obj3d.paint;
- {do the actual painting here}
- var
- i : integer;
- begin
- if ((numOfPoints = 0) or (numOfLines = 0)) then exit;
- if (not(scrPntUpdt)) then
- updateScreenPoints;
- for i := 1 to numOfLines do
- line( scrPoints[lines[i].fromP].sX,
- scrPoints[lines[i].fromP].sY,
- scrPoints[lines[i].toP].sX,
- scrPoints[lines[i].toP].sY );
- {it should be noted that calcPoint has to convert points to integers}
- end;
-
- (******************************************************************************
- * obj3d.readMe *
- ******************************************************************************)
- procedure obj3d.readMe;
- var
- tmp1,tmp2 : real;
- i,j : byte;
- begin
- read(elementFile, tmp1);
- numOfPoints := trunc(tmp1);
- for j := 1 to numOfPoints do begin
- read(elementFile, points[j].x);
- read(elementFile, points[j].y);
- read(elementFile, points[j].z);
- end; {for}
- read(elementFile, tmp1);
- numOfLines := trunc(tmp1);
- for j := 1 to numOfLines do begin
- read(elementFile, tmp1, tmp2);
- lines[j].fromP := trunc(tmp1);
- lines[j].toP := trunc(tmp2);
- end; {for}
- end; {obj3d.readMe}
-
- (******************************************************************************
- * obj3d.writeMe *
- ******************************************************************************)
- procedure obj3d.writeMe;
- var
- tmp1,tmp2 : real;
- i,j : byte;
- begin
- tmp1 := numOfPoints;
- write(elementFile, tmp1);
- for j := 1 to numOfPoints do begin
- write(elementFile, points[j].x);
- write(elementFile, points[j].y);
- write(elementFile, points[j].z);
- end; {for}
- tmp1 := numOfLines;
- write(elementFile, tmp1);
- for j := 1 to numOfLines do begin
- tmp1 := lines[j].fromP;
- tmp2 := lines[j].toP;
- write(elementFile, tmp1, tmp2);
- end;
- end;
-
- (*******************************************************************************
- * obj3d.calcLocation *
- *******************************************************************************)
- procedure obj3d.calcLocation;
- var
- ce : point3d;
- p : point3d;
- i : integer;
- begin
- ce := zeroPoint; { (0, 0, 0) -> ce }
- for i := 1 to numOfPoints do begin
- myCtm.transform(p, points[i]);
- ce.x := ce.x + p.x;
- ce.y := ce.y + p.y;
- ce.z := ce.z + p.z;
- end; {for}
- location.x := ce.x / numOfPoints;
- location.y := ce.y / numOfPoints;
- location.z := ce.z / numOfPoints;
- end; {obj3d.calcLocation}
-
- (*******************************************************************************
- * Obj3d.setToOrigin *
- *******************************************************************************)
- procedure Obj3d.setToOrigin;
- var
- i : integer;
- p : point3d;
- begin
- goto3dPos(0, 0, 0);
- for i := 1 to numOfPoints do begin
- myCtm.transform(p, points[i]);
- points[i] := p;
- end; {for}
- scrPntUpdt := False; (** Instead of that THING above **)
- myCtm.setUnit;
- location := zeroPoint;
- end; {BaseObject.setToOrign}
-
-
-
- (*******************************************************************************
- * ComplexObj.Open *
- *******************************************************************************)
- constructor ComplexObj.Open;
- begin
- BaseObject.Open(myName, color);
- numOfChilds := 0;
- end;
-
- (*******************************************************************************
- * ComplexObj.CloseMe *
- *******************************************************************************)
- destructor ComplexObj.CloseMe;
- var
- i : integer;
-
- begin
- for i := 1 to numOfChilds do
- dispose(childs[i],closeMe);
- baseObject.closeMe;
- end;
-
- (*******************************************************************************
- * ComplexObj.addSubObject *
- *******************************************************************************)
- function ComplexObj.addSubObject;
- var
- ret_code : word;
- begin
- if (numOfChilds >= maxSubObjects) then begin
- addSubObject := 255; {signal error}
- exit;
- end;
- inc(numOfChilds);
- childs[numOfChilds] := new(obj3dPtr, open(myName, zeroPoint, myColor));
- ret_code := childs[numOfChilds]^.load;
- if (ret_code = 0) then begin
- with refPoint do
- childs[numOfChilds]^.translate(round(x),
- round(y), round(z));
- ctms[numOfChilds].copy(childs[numOfChilds]^.myCtm);
- end; {if ret_c..}
- addSubObject := ret_code;
- end;
-
- (*******************************************************************************
- * complexObj.updateScreenPoints *
- *******************************************************************************)
- procedure complexObj.updateScreenPoints;
- var
- i : integer;
- begin
- for i := 1 to numOfChilds do begin
- childs[i]^.myCtm.multiply_2(ctms[i], myCtm);
- childs[i]^.updateScreenPoints;
- end;
- scrPntUpdt := True;
- end; {complexObj.updateScreenPoints}
-
- (*******************************************************************************
- * complexObj.getChildPtr *
- *******************************************************************************)
- function complexObj.getChildPtr;
- begin
- getChildPtr := childs[index];
- end;
-
- (*******************************************************************************
- * ComplexObj.rotateChild *
- *******************************************************************************)
- procedure ComplexObj.rotateChild;
- begin
- with childs[child]^ do begin
- myCtm.copy(ctms[child]);
- rotate(axis, deg);
- ctms[Child].copy(MyCtm);
- myCtm.Multiply(Self.myCtm);
- end;
- end;
-
- (*******************************************************************************
- * ComplexObj.scaleChild *
- *******************************************************************************)
- procedure ComplexObj.scaleChild;
- begin
- with childs[child]^ do begin
- myCtm.copy(ctms[child]);
- scale(axis, factor);
- ctms[Child].copy(MyCtm);
- myCtm.Multiply(Self.myCtm);
- end;
- end;
-
- (*******************************************************************************
- * ComplexObj.moveChild *
- *******************************************************************************)
- procedure ComplexObj.moveChild;
- begin
- with childs[child]^ do begin
- myCtm.copy(ctms[child]);
- move(axis, by);
- ctms[Child].copy(MyCtm);
- myCtm.Multiply(Self.myCtm);
- end;
- end;
-
- (******************************************************************************
- * complexObj.paint *
- ******************************************************************************)
- procedure complexObj.paint;
- var
- i : integer;
- begin
- if (not(scrPntUpdt)) then
- updateScreenPoints;
- for i := 1 to numOfChilds do
- childs[i]^.paint;
- end;
-
- procedure complexObj.writeMe;
- var
- i : integer;
- r : real;
- begin
- r := 0.0 + numOfChilds;
- write(elementFile, r);
- for i := 1 to numOfChilds do
- childs[i]^.writeMe(elementFile); {let all the kids write themselvs}
- end;
-
- (******************************************************************************
- * complexObj.readMe *
- ******************************************************************************)
- procedure complexObj.readMe;
- var
- i : integer;
- r : real;
- begin
- read(elementFile, r);
- numOfChilds := round(r);
- for i := 1 to numOfChilds do begin
- childs[i] := new(Obj3dPtr, Open('Child', ZeroPoint, myColor));
- childs[i]^.readMe(elementFile);
- childs[i]^.calcLocation;
- ctms[i].setUnit;
- end; {for}
- end; {complexObj.readMe}
-
- (******************************************************************************
- * complexObj.calcLocation *
- ******************************************************************************)
- procedure complexObj.calcLocation;
- var
- i : integer;
- begin
- location := zeroPoint;
- for i := 1 to numOfChilds do
- with childs[i]^ do begin
- calcLocation;
- self.location.x := location.x + self.location.x;
- self.location.y := location.y + self.location.y;
- self.location.z := location.z + self.location.z;
- end; {with}
- with location do begin
- x := x / numOfChilds;
- y := y / numOfChilds;
- z := z / numOfChilds;
- end; {with..}
- end; {complexObj.calclocation}
-
- (******************************************************************************
- * complexObj.move *
- ******************************************************************************)
- procedure complexObj.move;
- var
- i : integer;
- begin
- (* for i := 1 to numOfChilds do
- with childs[i]^ do
- case axis of
- x : location.x := location.x + by;
- y : location.y := location.y + by;
- z : location.z := location.z + by;
- end; {case} *)
- baseObject.move(axis, by);
- end; {complexObj.move}
-
- (******************************************************************************
- * complexObj.rotate *
- ******************************************************************************)
- procedure complexObj.rotate;
- var
- i : integer;
- sint, cost : real;
- begin
- (* cost := cos(deg / 180.0 * 3.1415926535897932385);
- sint := sin(deg / 180.0 * 3.1415926535897932385);
- for i := 1 to numOfChilds do
- with childs[i]^ do
- case axis of
- x : begin
- location.y := location.y * cost -
- location.z * sint;
- location.z := location.y * sint +
- location.z * cost;
- end; {x}
- y : begin
- location.x := location.x * cost +
- location.z * sint;
- location.z := location.z * cost -
- location.x * sint;
- end; {y}
- z : begin
- location.x := location.x * cost -
- location.y * sint;
- location.y := location.y * cost +
- location.x * sint;
- end; {z}
- end; {case} *)
- baseObject.rotate(axis, deg);
- end; {complexObj.rotate}
-
- (******************************************************************************
- * complexObj.scale *
- ******************************************************************************)
- procedure complexObj.scale;
- var
- i : integer;
- begin
- (* for i := 1 to numOfChilds do
- with childs[i]^ do
- case axis of
- x : location.x := location.x * factor;
- y : location.y := location.y * factor;
- z : location.z := location.z * factor;
- end; {case} *)
- baseObject.scale(axis, factor);
- end; {complexObj.scale}
-
- end.
-