perm filename EUCLID.FAI[SAI,BGB] blob sn#144450 filedate 1978-02-26 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00026 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00004 00002	TITLE EUCLID - EUCLIDEAN ROUTINES - BRUCE G. BAUMGART - JULY 1972.
C00006 00003	SUBR(TRANSLATE,FRMOBJ,DX,DY,DZ)	       OBJECT TRANSLATION WRT FRAME.
C00008 00004	SUBR(ROTATE,FRMOBJ,CX,CY,CZ)  		OBJECT ROTATION WRT FRAME.
C00011 00005	
C00013 00006	SUBR(SHRINK,FRMOBJ,KKX,KKY,KKZ)	      DILATION-REFLECTION WRT FRAME.
C00014 00007	SUBR(APTRAN,OBJECT,TRAN) APPLY EUCLIDEAN TRANSFORMATION TO THE OBJECT.
C00018 00008	SUBN(ROTOR)
C00020 00009	SUBR(INTRAN,TRAN)		INVERT A TRANSFORMATION.
C00022 00010	SUBR(MKROT1,PAN,TILT,SWING)
C00025 00011	SUBR(MKQFRM,DX,DY,DZ)		MAKE FRAME WITH RESPECT TO VECTOR.
C00027 00012	SUBR(NORM,FRAME)	 NORMALIZE A FRAME MATRIX.
C00038 00013	SUBR(ORTHO2,QFRAME)		ORTHOGONALIZE A MATRIX.
C00041 00014	SUBR(ANGL3V,VERT1,VERT2,VERT3)			ANGLE TRI-VERTEX.
C00044 00015	SUBR(DISTAN,V1,V2)		DISTANCE BETWEEN TWO VERTICES.
C00045 00016	 ENORM & VNORM
C00047 00017	SUBR(QEV,EDGE,VERTEX)		DISTANCE VERTEX TO EDGE.
C00049 00018	SUBR(ZDEPTH,FACE,VERTEX)	ZPP DEPTH.
C00051 00019		DEFINE TJOINT(Q,V)<CAR Q,2(V)>
C00053 00020	SUBR(PPROJ,CAMERA,WORLD)
C00056 00021	SUBR(VPROJ,VERTEX,CAMERA)	VERTEX PERSPECTIVE PROJECTION.
C00059 00022	SUBR(UNPROJECT,VERTEX,CAMERA)
C00061 00023	SUBR(FACOEF,BF)		FACE COEFFICIENTS. BF>0 WC, BF<0 PP.
C00064 00024	SUBR(WITH3D,FACE,X,Y,Z)		TEST FOR LOCUS WITHIN FACE 3D.
C00067 00025	SUBR(SOLANG,VERTEX)	DIHEDRAL ANGLE AT A PIERCING VERTEX.
C00069 00026	END
C00070 ENDMK
C⊗;
TITLE EUCLID - EUCLIDEAN ROUTINES - BRUCE G. BAUMGART - JULY 1972.

	.INSERT MN
	EXTERN ECW,ECCW,OTHER
	EXTERN BGET,FCW,FCCW,VCW,VCCW
	EXTERN MKCOPY,MKFRAME,KLNODE
	EXTERN SIN,COS,SQRT,ATAN,ATAN2,ASIN,ACOS,LOG,HALFPI,PI,TWOPI

COMMENT ⊗----------------------------------------------------------------------

EUCLIDEAN TRANSFORMATIONS

	TRANS	←	TRANSL(XWD(FRAME,BODY),DX,DY,DZ);
	TRANS	←	ROTATE(XWD(FRAME,BODY),WX,WY,WZ);
	TRANS	←	SHRINK(XWD(FRAME,BODY),KX,KY,KZ);
	TRANS	←	APTRAN(ENTITY,TRANS);
			{ROTOR}
	TRANS	←	INTRAN(TRAN);

FRAME MAKERS

	TRANS	←	MKROT1(PAN,TILT,SWING);		MAKE FROM EULER ANGLES.
	TRANS	←	MKFFRM(FACE);			MAKE FACE FRAME.
	TRANS	←	MKQFRM(WX,WY,WZ);		MAKE FROM ROTATION VECTOR.

ORTHONORMALIZATION.

	NORM(FRAME)	;NORMALIZATION TO UNIT VECTORS.
	ORTHO1(FRAME)	;ORTHOGONALIZE BY WORST CASE.
	ORTHO2(FRAME)	;ORTHOGONALIZE BY K ← (I CROSS J), J ← (K CROSS I).

GEOMETRIC MEASURE ROUTINES.

	DETERM(FRAME)
	ANGL3V(V1,V2,V3)
	DISTANCE(ENTITY,ENTITY);

VECTOR ROUTINES.

TENSOR ROUTINES.

SPATIAL PREDICATES.

IMAGE PROJECTION.

------------------------------------------------------------------------------⊗
SUBR(TRANSLATE,FRMOBJ,DX,DY,DZ)	       ;OBJECT TRANSLATION WRT FRAME.
COMMENT .-----------------------------------------------------------.
	CALL(MKFRAME)
	HRLZI DX↔HRRI XWC(1)↔BLT ZWC(1)	;DELTA'S OF TRANSLATION.
↑QTRAN:	DAC 1,TMP1			;SECOND ENTRY.
	MOVM 2,FRMOBJ↔CDR 2,2↔DAC 2,OBJECT
	HLRE 1,FRMOBJ↔SKIPGE 1↔GO[
		SETZ 1,↔JUMPE 2,.+1	;JUMP WHEN NO OBJECT.
		CALL(BGET,OBJECT)	;GET BODY OF THE OBJECT.
		FRAME 1,1↔GO .+1]	;GET FRAME OF THE BODY.
	DAC 1,REFRAM			;FRAME OF REFERENCE.
	LAC 1,TMP1↔SKIPN REFRAM↔GO L1
L0:	SETQ(TMP2,{MKCOPY,REFRAM})
	CALL(INTRAN,TMP2)
	CALL(APTRAN,TMP2,TMP1)
	CALL(APTRAN,TMP2,REFRAM)
	CALL(KLNODE,TMP1)
	LAC 1,TMP2↔DAC 1,TMP1		;TMP1 ← TMP2.
L1:	SKIPN OBJECT↔POP4J		;RETURN TRANSFORMATION.
	CALL(APTRAN,OBJECT,TMP1)
	CALL(KLNODE,TMP1)
	LAC 1,OBJECT↔POP4J		;RETURN THE OBJECT.
DECLARE{TMP1,TMP2,REFRAM,OBJECT}
ENDR TRANSLATE;3/18/73(BGB)------------------------------------------

SUBR(ROTATE,FRMOBJ,CX,CY,CZ)  		;OBJECT ROTATION WRT FRAME.
COMMENT .---------------------------------------------------------------------.

;COMPONENTS OF ROTATION VECTOR.
	SKIPE 1,CX↔FMPR 1,1↔LAC  1
	SKIPE 1,CY↔FMPR 1,1↔FADR 1
	SKIPE 1,CZ↔FMPR 1,1↔FADR 1
	JUMPE POP4J.
	SETQ(W,{SQRT↑,0})			;RADIANS OF ROTATION.
	SETQ(C,{COS,W})
	SETQ(S,{SIN,W})
	MOVSI (<1.0>)↔FDVR W
	FMPRM CX↔FMPRM CY↔FMPRM CZ		;NORMALIZE INTO THE STACK.

;COMPUTE ROTATION MATRIX.
;1/ (1-CW)*CX↑2  +    CW    2/ (1-CW)*CX*CY + CZ*SW   3/ (1-CW)*CX*CZ - CY*SW
;4/ (1-CW)*CX*CY - CZ*SW    5/ (1-CW)*CY↑2  +    CW   6/ (1-CW)*CY*CZ + CX*SW
;7/ (1-CW)*CX*CZ + CY*SW    8/ (1-CW)*CY*CZ - CX*SW   9/ (1-CW)*CZ↑2  +    CW

	MOVSI 1,(<1.0>)↔FSBR 1,C		; (1-C) IN ALL POSITIONS.
	LAC[XWD 1,2]↔BLT 9

	FMPR 1,CX↔FMPR 1,CX↔FADR 1,C		;DIAGONAL ELEMENTS.
	FMPR 5,CY↔FMPR 5,CY↔FADR 5,C
	FMPR 9,CZ↔FMPR 9,CZ↔FADR 9,C

	LAC CX↔FMPR CY↔FMPR 2,↔FMPR 4,		;(1-CW) PRODUCTS.
	LAC CX↔FMPR CZ↔FMPR 3,↔FMPR 7,
	LAC CY↔FMPR CZ↔FMPR 6,↔FMPR 8,

	LAC CX↔FMPR S↔FADR 6,↔FSBR 8,		;CX*S PRODUCTS.
	LAC CY↔FMPR S↔FADR 7,↔FSBR 3,		;CY*S
	LAC CZ↔FMPR S↔FADR 2,↔FSBR 4,		;CZ*S

	CALL(MKNODE↑,1)↔DAC 1,TMP1
	MOVSI 2↔HRRI IY(1)↔BLT KZ(1)
	GO QTRAN
	DECLARE{W,C,S,TMP1}
ENDR ROTATE; BGB & HANS P. MORAVEC & MACSYMA 3 JUNE 1974 ----------------------
COMMENT ⊗
SUBR(ROTATE,FRMOBJ,WX,WY,WZ)  		;OBJECT ROTATION WRT FRAME.
COMMENT .-----------------------------------------------------------.

;COMPONENTS OF ROTATION VECTOR.
	SKIPE 1,WX↔FMPR 1,1↔DAC 1,4
	SKIPE 2,WY↔FMPR 2,2↔DAC 2,5
	SKIPE 3,WZ↔FMPR 3,3
	FADR 1,2↔FADR 1,3↔JUMPE 1,POP1J.
	SETQ(W,{SQRT↑,1})

;ROTATION AXIS FRAME OF REFERENCE.
	SETQ(TMP1,{MKFRAME})↔DAC 1,7
	LAC 1,WX↔FDVR 1,W↔DAC 1,IX(7)
	LAC 2,WY↔FDVR 2,W↔DAC 2,IY(7)
	LAC 3,WZ↔FDVR 3,W↔DAC 3,IZ(7)
	MOVM 2↔CAMG [0.99]↔GO .+3	;W ALMOST COLINEAR WITH J VECTOR.
	SETZM JY(7)↔DAC 2,JX(7)		;CHANGE J VECTOR.
	CALL(ORTHO2,TMP1)↔CALL(NORM,TMP1)

;ROTATION ABOUT I UNIT VECTOR.
	SETQ(TMP2,{MKFRAME})
	CALL(COS,W)↔LAC 2,TMP2↔DAC 1,JY(2)↔DAC   1,KZ(2)
	CALL(SIN,W)↔LAC 2,TMP2↔DAC 1,JZ(2)↔MOVNM 1,KY(2)
	CALL(APTRAN,TMP2,TMP1)

	LAC 1,TMP1			;TRANSPOSITION.
	LAC IY(1)↔EXCH JX(1)↔DAC IY(1)
	LAC IZ(1)↔EXCH KX(1)↔DAC IZ(1)
	LAC JZ(1)↔EXCH KY(1)↔DAC JZ(1)
	CALL(APTRAN,TMP1,TMP2)↔CALL(KLNODE,TMP2)
	LAC 1,TMP1↔GO QTRAN
DECLARE{W,TMP1,TMP2,TMP3,REFRAM,OBJECT}
ENDR ROTATE;3/18/73(BGB)---------------------------------------------
⊗
SUBR(SHRINK,FRMOBJ,KKX,KKY,KKZ)	      ;DILATION-REFLECTION WRT FRAME.
COMMENT .-----------------------------------------------------------.
	CALL(MKFRAME)
	SKIPN 2,KKX↔MOVSI 2,(1.0)↔DAC 2,IX(1)
	SKIPN 2,KKY↔MOVSI 2,(1.0)↔DAC 2,JY(1)
	SKIPN 2,KKZ↔MOVSI 2,(1.0)↔DAC 2,KZ(1)↔GO QTRAN
ENDR SHRINK;3/18/73(BGB)---------------------------------------------
SUBR(APTRAN,OBJECT,TRAN); APPLY EUCLIDEAN TRANSFORMATION TO THE OBJECT.
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{B,F,E,V,X,Y,Z,TRN,N,OBJ,E0}
	SKIPE OBJ,OBJECT↔SKIPN TRN,TRAN↔POP2J	;IGNORE ZERO ARGS.
	MOVM 1,(OBJ)↔JUMPE 1,LROTA	;GET TYPE OF OBJECT.
	TLNE 1,(1B9)↔GO LROTA		;FRAME.
	ANDI 1,17↔GO @.+1(1)		;DISPATCH ON TYPE OF OBJECT.
	POP2J.↔POP2J.↔POP2J.↔CROTA	;FRAME EMPTY UNIVERSE SUN
	CROTA↔POP2J.↔POP2J.↔POP2J.	;CAMERA WORLD WINDOW IMAGE
	POP2J.↔POP2J.↔POP2J.↔POP2J.	;TEXT XNODE YNODE ZNODE
	BROTA↔FROTA↔EROTA↔VROTA		;BODY FACE EDGE VERTEX
;....................................................................
LROTA:	LAC V,OBJ↔SETZM TMP2#↔GO .+3	;FRAME CASE.
CROTA:	FRAME V,OBJ↔DAC V,TMP2#		;CAMERA & SUN CASE.
	CALL(ROTOR)
	PUSH P,XWC(TRN)↔PUSH P,YWC(TRN)↔PUSH P,ZWC(TRN)
	SETZM XWC(TRN)↔SETZM YWC(TRN)↔SETZM ZWC(TRN)
	ADDI V,3↔CALL(ROTOR)
	ADDI V,3↔CALL(ROTOR)
	ADDI V,3↔CALL(ROTOR)
	POP P,ZWC(TRN)↔POP P,YWC(TRN)↔POP P,XWC(TRN)
	SKIPN TMP2↔POP2J
	CALL(NORM,TMP2#)
	CALL(ORTHO1,TMP2#)↔POP2J
;....................................................................
BROTA:	LAC B,OBJ			;BODY ROTATION.
	TESTZ B,BDVBIT↔GO L2		;DON'T MOVE VERTICES.
	LAC V,B		   		;1ST VERTEX.
L1:	PVT V,V
	CAMN V,OBJ↔GO L2		;SKIP WHEN VERTEX.
	CALL(ROTOR)↔GO L1		;ROTATE VERTEX.
L2:	LAC B,OBJ
	TESTZ B,BDLBIT↔GO L3		;DON'T MOVE FRAME.
	FRAME V,B↔SKIPN V↔GO L3
	DAC V,TMP#↔PUSH P,B
	CALL(APTRAN,V,TRN)		;BODY'S FRAME.
	CALL(NORM,TMP#)
	CALL(ORTHO1,TMP#)↔POP P,B
;PARTS OF THIS BODY.
L3:	TESTZ B,BDPBIT↔POP2J		;DON'T MOVE PARTS.
	SON N,B↔JUMPE N,POP2J.
L4:	CALL(APTRAN,N,N,TRN)
	POP P,N↔LAC B,OBJECT
	BRO N,N↔SON 0,B
	CAME 0,N↔GO L4↔POP2J
;....................................................................
FROTA:	LAC F,OBJ↔NCNT N,F↔MOVMS N	;FACE ROTATION.
	PED E,F↔DAC E,E0↔JUMPE E0,[	;VERTEX FACE.
	PFACE B,F↔PVT V,B↔CALL(ROTOR)↔POP2J]
	PCW 0,E↔SKIPN N↔CAMN 0,E↔GO[	;WIRE OR SHELL FACE.
	SETQ(V,{VCW,E,F})↔CALL(ROTOR)↔GO .+1]
L5:	SETQ(V,{VCCW,E,F})
	CALL(ROTOR)↔CALL(ECCW,E,F)
	CAMN 1,E↔POP2J			;END OF WIRE FACE.
	LAC E,1↔CAMN E,E0↔POP2J		;END OF NORMAL FACE.
	SOJN N,L5↔POP2J			;END OF SHELL FACE.
;....................................................................
EROTA:	LAC E,OBJ			;EDGE ROTATION
	PVT V,E↔CALL(ROTOR)
	NVT V,E↔CALL(ROTOR)↔POP2J
VROTA:	LAC V,OBJ↔CALL(ROTOR)↔POP2J	;VERTEX ROTATION.
ENDR APTRAN;1/14/73(BGB)------------------------------------------
SUBN(ROTOR)
COMMENT ⊗------------------------------------------------------------
;  APTRAN's inner most subroutine.
;  Expects arguments in V and Q. Clobbers 1,2,X,Y,Z.
;
;	X ← XWC(V);
;	Y ← YWC(V);
;	Z ← ZWC(V);
;
;	XWC(V) ← X*IX(Q) + Y*JX(Q) + Z*KX(Q) + XWC(Q);
;	YWC(V) ← X*IY(Q) + Y*JY(Q) + Z*KZ(Q) + YWC(Q);
;	ZWC(V) ← X*IZ(Q) + Y*JZ(Q) + Z*KZ(Q) + ZWC(Q);
⊗
	ACCUMULATORS{B,F,E,V,X,Y,Z,Q}
	
	LAC X,XWC(V)↔LAC Y,YWC(V)↔LAC Z,ZWC(V)

	LAC 1,IX(Q)↔CAMN 1,[1.0]↔SKIPA 1,X↔FMPR 1,X
	SKIPE 2,JX(Q)↔GO[FMPR 2,Y↔FADR 1,2↔GO .+1]
	SKIPE 2,KX(Q)↔GO[FMPR 2,Z↔FADR 1,2↔GO .+1]
	SKIPE 2,XWC(Q)↔FADR 1,2↔DAC 1,XWC(V)

	LAC 1,JY(Q)↔CAMN 1,[1.0]↔SKIPA 1,Y↔FMPR 1,Y
	SKIPE 2,IY(Q)↔GO[FMPR 2,X↔FADR 1,2↔GO .+1]
	SKIPE 2,KY(Q)↔GO[FMPR 2,Z↔FADR 1,2↔GO .+1]
	SKIPE 2,YWC(Q)↔FADR 1,2↔DAC 1,YWC(V)

	LAC 1,KZ(Q)↔CAMN 1,[1.0]↔SKIPA 1,Z↔FMPR 1,Z
	SKIPE 2,JZ(Q)↔GO[FMPR 2,Y↔FADR 1,2↔GO .+1]
	SKIPE 2,IZ(Q)↔GO[FMPR 2,X↔FADR 1,2↔GO .+1]
	SKIPE 2,ZWC(Q)↔FADR 1,2↔DAC 1,ZWC(V)

	POP0J
ENDR ROTOR;3/18/73(BGB)-------------------------------------------
SUBR(INTRAN,TRAN)		;INVERT A TRANSFORMATION.
COMMENT .-----------------------------------------------------------.
	Q ←← 6
	LAC 2,TRAN
	MOVSI XWC(2)↔HRRI XWC+Q↔BLT KZ+Q

;XWC' ← -(XWC*IX + YWC*IY + ZWC*IZ);
	LAC 1,XWC+Q↔FMPR 1,IX+Q
	LAC YWC+Q↔FMPR IY+Q↔FADR 1,0
	LAC ZWC+Q↔FMPR IZ+Q↔FADR 1,0
	MOVNM 1,XWC(2)

;YWC' ← -(XWC*JX + YWC*JY + ZWC*JZ);
	LAC 1,XWC+Q↔FMPR 1,JX+Q
	LAC YWC+Q↔FMPR JY+Q↔FADR 1,0
	LAC ZWC+Q↔FMPR JZ+Q↔FADR 1,0
	MOVNM 1,YWC(2)

;ZWC' ← -(XWC*KX + YWC*KY + ZWC*KZ);
	LAC 1,XWC+Q↔FMPR 1,KX+Q
	LAC YWC+Q↔FMPR KY+Q↔FADR 1,0
	LAC ZWC+Q↔FMPR KZ+Q↔FADR 1,0
	MOVNM 1,ZWC(2)

;TRANSPOSE ROTATION MATRIX.
	DAC JX+Q,IY(2)
	DAC KX+Q,IZ(2)
	DAC IY+Q,JX(2)
	DAC KY+Q,JZ(2)
	DAC IZ+Q,KX(2)
	DAC JZ+Q,KY(2)
	LAC 1,2
	POP1J
ENDR INTRAN;3/18/73(BGB)---------------------------------------------
SUBR(MKROT1,PAN,TILT,SWING)
COMMENT .-----------------------------------------------------------.
	SETQ(CP,{COS,PAN})↔	SETQ(SP,{SIN,PAN})
	SETQ(CT,{COS,TILT})↔	SETQ(ST,{SIN,TILT})
	SETQ(CS,{COS,SWING})↔	SETQ(SS,{SIN,SWING})
	CALL(MKFRAME)

	LAC SP↔FMP CT↔FMP SS↔DAC 2↔LAC CP↔FMP CS↔FSB 2↔DAC IX(1)
	LAC CP↔FMP CT↔FMP SS↔DAC 2↔LAC SP↔FMP CS↔FAD 2↔DAC IY(1)
	LAC ST↔FMP SS↔DAC IZ(1)

	LAC SP↔FMP CT↔FMP CS↔DAC 2↔LAC CP↔FMP SS↔FAD 2↔MOVNM JX(1)
	LAC CP↔FMP CT↔FMP CS↔DAC 2↔MOVN SP↔FMP SS↔FAD 2↔DAC JY(1)
	LAC ST↔FMP CS↔DAC JZ(1)

	LAC SP↔FMP ST↔DAC KX(1)
	LAC CP↔FMP ST↔MOVNM KY(1)
	LAC CT↔DAC KZ(1)↔POP3J
	DECLARE{CP,CT,CS,SP,ST,SS}
ENDR MKROT1;10/30/73(BGB)--------------------------------------------

SUBR(MKFFRM,FACE)	;MAKE FACE FRAME.
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{F,E,E0,V,X,Y,Z,N}

	LAC F,FACE↔PED E,F↔DAC E,E0
	SETZB X,Y↔SETZB Z,N
L1:	SETQ(V,{VCCW,E,F})↔SETQ(E,{ECCW,E,F})
	FADR X,XWC(V)↔FADR Y,YWC(V)↔FADR Z,ZWC(V)
	CAME E,E0↔AOJA N,L1↔AOS N

;CENTER OF FACE BECOMES ORIGIN.
	FLOAT N,↔FDVR X,N↔FDVR Y,N↔FDVR Z,N
	SETQ(F,{MKFRAME})↔DAC F,FRM#
	DAC X,XWC(F)↔DAC Y,YWC(F)↔DAC Z,ZWC(F)

;FIRST TWO VECTORS.
	SETQ(V,{VCW,E0,FACE})
	LAC XWC(V)↔FSBR X↔DAC IX(F)
	LAC YWC(V)↔FSBR Y↔DAC IY(F)
	LAC ZWC(V)↔FSBR Z↔DAC IZ(F)
	SETQ(V,{VCCW,E0,FACE})
	LAC XWC(V)↔FSBR X↔DAC JX(F)
	LAC YWC(V)↔FSBR Y↔DAC JY(F)
	LAC ZWC(V)↔FSBR Z↔DAC JZ(F)
	CALL(ORTHO2,FRM)
	CALL(NORM,FRM)
	CALL(ORTHO1,FRM)
	LAC 1,FRM↔POP1J
ENDR MKFFRM;2/19/74(BGB)---------------------------------------------

SUBR(MKQFRM,DX,DY,DZ)		;MAKE FRAME WITH RESPECT TO VECTOR.
COMMENT .-----------------------------------------------------------.

;NORMALIZE THE COMPONENTS OF THE VECTOR.
	SKIPE 1,DX↔FMPR 1,1↔DAC 1,4
	SKIPE 2,DY↔FMPR 2,2↔DAC 2,5
	SKIPE 3,DZ↔FMPR 3,3
	FADR 1,2↔FADR 1,3
	SETQ(R,{SQRT↑,1})

;ROTATION AXIS FRAME OF REFERENCE.
	SETQ(TMP1,{MKFRAME})↔DAC 1,7↔SKIPN R↔POP3J

	LAC 1,DX↔DAC 1,XWC(7)↔FDVR 1,R↔DAC 1,IX(7)↔DAC 1,JY(7)
	LAC 2,DY↔DAC 2,YWC(7)↔FDVR 2,R↔DAC 2,IY(7)↔DAC 2,JX(7)
	LAC 3,DZ↔DAC 3,ZWC(7)↔FDVR 3,R↔DAC 3,IZ(7)↔SETZM JZ(7)
	MOVM 3↔CAMLE[0.999]↔MOVNM JY(7)

	CALL(ORTHO2,TMP1)
	CALL(NORM,TMP1)
	LAC 1,TMP1

	POP3J
DECLARE{R,TMP1}
ENDR MKQFRM;3/6/74(BGB)----------------------------------------------
SUBR(NORM,FRAME)	; NORMALIZE A FRAME MATRIX.
COMMENT .-----------------------------------------------------------.
;ACCUMULATORS:
;	05 06 07	IX  IY  IZ
;	10 11 12	JX  JY  JZ
;	13 14 15	KX  KY  KZ.
	SAVAC(15)
	MOVS FRAME↔HRRI 5↔BLT 15

; R ← SQRT(A↑2+B↑2+C↑2); A←A/R; B←B/R; C←C/R;
	FOR Q IN (5,10,13){
	MOVM 1,Q↔CAMG 1,[1.0E-8]↔SETZB 1,Q↔FMPR 1,1
	MOVM 1+Q↔CAMG 0,[1.0E-8]↔SETZB 1+Q↔FMPR↔FADR 1,0
	MOVM 2+Q↔CAMG 0,[1.0E-8]↔SETZB 2+Q↔FMPR↔FADR 1,0
	SKIPE 1↔CAMN 1,[1.0]↔GO .+6↔CALL(SQRT,1)
	FDVR Q,1↔FDVR Q+1,1↔FDVR Q+2,1}

;PUT'EM DOWN.
	LAC 1,FRAME
	MOVSI 5↔HRRI IX(1)↔BLT KZ(1)
	GETAC(15)↔POP1J
ENDR NORM;1/14/73----------------------------------------------------

SUBR(ORTHO1,FRAME)		; ORTHOGONALIZE AN ORIENTATION MATRIX.
COMMENT .-----------------------------------------------------------.
;IT IS ASSUMED THAT THE ROW VECTORS ARE UNIT VECTORS.
	X←←0 ↔ Y←←1 ↔ Z←←2		;ADDRESS DISPLACEMENTS.
	Q←←9 ↔ R←←13 ↔ A←←14 ↔ B←←15  	;ACCUMULATORS.
	SAVAC(15)↔SETOM FLG# 		;FIRST TIME THRU FLAG.
L0:	LAC R,FRAME
	MOVSI Q,IX(R)↔BLT Q,KZ		;FIRST NINE ACCUMULATORS.

;DOT EACH ROW VECTOR INTO THE NEXT ROW.
	FMPR IX,JX↔FMPR IY,JY↔FMPR IZ,JZ
	FADR IX,IY↔FADR IX,IZ
	FMPR JX,KX↔FMPR JY,KY↔FMPR JZ,KZ
	FADR JX,JY↔FADR JX,JZ
	FMPR KX,IX(R)↔FMPR KY,IY(R)↔FMPR KZ,IZ(R)
	FADR KX,KY↔FADR KX,KZ

;TAKE ABSOLUTE VALUES AND FIND THE WORST TOTAL COSINE.
	MOVMS IX↔MOVMS JX↔MOVMS KX
	LAC Q,KX↔FADR KX,JX↔FADR JX,IX↔FADR Q,IX
	EXCH Q,JX↔SETZM SIGN#
	MOVEI 1,IX(R)↔MOVEI 2,JX(R)↔MOVEI 3,KX(R)	;GET ROW POINTERS.
	CAML Q,IX↔GO .+4
	EXCH 2,1↔EXCH Q,IX↔SETCMM SIGN 	;GET 2 BIGGER THAN 1.
	CAML KX,Q↔GO .+4
	EXCH 3,2↔EXCH KX,Q↔SETCMM SIGN 	;GET 3 BIGGER THAN 2.
	CAMG KX,[0.00001]↔GO L1	  ;GOOD ENUF FOR GOVERNMENT WORK.

;STRAIGHTEN UP THE WORST VECTOR.
	LAC A,Y(1)↔FMPR A,Z(2)
	LAC B,Y(2)↔FMPR B,Z(1)↔FSBR A,B↔DAC A,X(3)
	MOVM A,A↔CAMG A,[1.0E-8]↔SETZM X(3)
	LAC A,X(2)↔FMPR A,Z(1)
	LAC B,X(1)↔FMPR B,Z(2)↔FSBR A,B↔DAC A,Y(3)
	MOVM A,A↔CAMG A,[1.0E-8]↔SETZM Y(3)
	LAC A,X(1)↔FMPR A,Y(2)
	LAC B,X(2)↔FMPR B,Y(1)↔FSBR A,B↔DAC A,Z(3)
	MOVM A,A↔CAMG A,[1.0E-8]↔SETZM Z(3)
	SKIPE SIGN↔GO[MOVNS X(3)↔MOVNS Y(3)↔MOVNS Z(3)↔GO .+1]
	SKIPN FLG↔GO L1↔SETZM FLG↔GO L0
L1:	GETAC(15)↔POP1J
ENDR ORTHO1;1/14/73(BGB)---------------------------------------------
SUBR(ORTHO2,QFRAME)		;ORTHOGONALIZE A MATRIX.
COMMENT .-----------------------------------------------------------.
;ACCEPT I; K' ← I CROSS J; J' ← K CROSS I;
	LAC 1,QFRAME
	SETZM KX(1)↔SETZM KY(1)↔SETZM KZ(1)
	MOVS QFRAME↔HRRI 1↔BLT 9
	LAC 12,4↔LAC 13,5↔LAC 14,6	;SAVE J VECTOR.
;VECTOR-K ← VECTOR-I CROSS VECTOR-J.
	LAC 2↔FMP 6↔DAC 7
	LAC 5↔FMP 3↔FSB 7,
	LAC 4↔FMP 3↔DAC 8
	LAC 1↔FMP 6↔FSB 8,
	LAC 1↔FMP 5↔DAC 9
	LAC 4↔FMP 2↔FSB 9,
;VECTOR-J ← VECTOR-K CROSS VECTOR-I.
	LAC 8↔FMP 3↔DAC 4
	LAC 2↔FMP 9↔FSB 4,
	LAC 1↔FMP 9↔DAC 5
	LAC 7↔FMP 3↔FSB 5,
	LAC 7↔FMP 2↔DAC 6
	LAC 1↔FMP 8↔FSB 6,
	LAC 15,QFRAME↔MOVSI 1
	HRRI IX(15)↔BLT KZ(15)
	LAC 1,QFRAME↔POP1J
ENDR ORTHO2;3/30/73(BGB)---------------------------------------------

SUBR(DETERM,FRAME)
COMMENT .-----------------------------------------------------------.
	MOVS FRAME↔HRRI 1↔BLT 9
	LAC 5↔FMP 9↔LAC 12,
	LAC 6↔FMP 8↔FSB 12,↔FMP 1,12
	LAC 6↔FMP 7↔LAC 12,
	LAC 4↔FMP 9↔FSB 12,↔FMP 2,12↔FAD 1,2
	LAC 4↔FMP 8↔LAC 12,
	LAC 5↔FMP 7↔FSB 12,↔FMP 3,12↔FAD 1,3↔POP1J
ENDR DETERM;4/1/73(BGB)----------------------------------------------
SUBR(ANGL3V,VERT1,VERT2,VERT3)			;ANGLE TRI-VERTEX.
COMMENT .-----------------------------------------------------------.
;ANGLE V1,V2,V3 CCW; RETURNS VALUE 0 TO 2π.
	V1 ←← 13
	V2 ←← 14
	V3 ←← 15

;DETERMINE WHETHER THE ANGLE IS MORE OR LESS THAN PI.

	LAC V1,VERT1↔MOVSI XWC(V1)↔HRRI 1↔BLT 3
	LAC V2,VERT2↔MOVSI XWC(V2)↔HRRI 4↔BLT 6
	LAC V3,VERT3↔MOVSI XWC(V3)↔HRRI 7↔BLT 9
	FSBR 1,4↔FSBR 2,5↔FSBR 3,6		;V1' ← (V1-V2).
	FSBR 7,4↔FSBR 8,5↔FSBR 9,6		;V3' ← (V3-V2).
	LAC 2↔FMP 9↔LAC 4,↔LAC 3↔FMP 8↔FSB 4,	;V2' ← (V1 X V3).
	LAC 3↔FMP 7↔LAC 5,↔LAC 1↔FMP 9↔FSB 5,
	LAC 1↔FMP 8↔LAC 6,↔LAC 2↔FMP 7↔FSB 6,
	FADR 1,4↔FADR 2,5↔FADR 3,6		;V1" ← (V1'+V2').
	FADR 7,4↔FADR 8,5↔FADR 9,6		;V3" ← (V3'+V2').

;DETERM NGEATIVE INDICATES CCW ORDER, 0 TO π.
;DETERM POSITIVE INDICATES CW  ORDER, π T0 2π.
	CALL({DETERM+3},0)
	SKIPL 1↔SKIPA 1,PI↔SETZ 1,↔PUSH P,1

;COSINE LAW.
	CALL(DISTANCE,V2,V1)↔PUSH P,1
	CALL(DISTANCE,V2,V3)↔PUSH P,1
	CALL(DISTANCE,V1,V3)
	FMPR 1,1↔MOVNS 1
	POP P,2↔LAC 2↔FMPR 2,2
	POP P,3↔FMP 3↔FMPR 3,3
	FSC 1↔FADR 1,2↔FADR 1,3
	FDVR 1,0↔CALL(ACOS,1)
	POP P,0↔FADR 1,0↔POP3J
ENDR ANGL3V;4/1/73(BGB)----------------------------------------------
SUBR(DISTAN,V1,V2)		;DISTANCE BETWEEN TWO VERTICES.
COMMENT .-----------------------------------------------------------.
	LAC 1,V1↔LAC 2,V2
	LAC XWC(1)↔FSBR XWC(2)↔FMPR↔DAC 3
	LAC YWC(1)↔FSBR YWC(2)↔FMPR↔FADRM 3
	LAC ZWC(1)↔FSBR ZWC(2)↔FMPR↔FADR 3
	CALL(SQRT,0)↔POP2J
ENDR DISTAN;2/10/73(BGB)---------------------------------------------
COMMENT ⊗ ENORM & VNORM

SUBR(ENORM,BODY)	     ;COMPUTE EDGE NORMALS FROM FACE NORMALS.
COMMENT .-----------------------------------------------------------.
 	ACCUMULATORS{E,F1,F2}
	LAC E,BODY
L1:	PED E,E↔CAMN E,BODY↔POP1J
	PFACE F1,E↔NFACE F2,E
	LAC AA(F1)↔FAD AA(F2)↔FSC -1↔MOVNM AA(E)
	LAC BB(F1)↔FAD BB(F2)↔FSC -1↔MOVNM BB(E)
	LAC CC(F1)↔FAD CC(F2)↔FSC -1↔MOVNM CC(E)
	GO L1
ENDR ENORM;1/14/73(BGB)----------------------------------------------

SUBR(VNORM,BODY)	;COMPUTE VERTEX NORMALS FROM EDGE NORMALS.
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{V,E,E0,A,B,C}
	LAC V,BODY
L1:	PVT V,V↔CAMN V,BODY↔POP1J
	PED E,V↔SKIPN E0,E↔POP1J   ;VERTEX BODY CASE.
	SETZB 0,A↔SETZB B,C
L2:	FAD A,AA(E)↔FAD B,BB(E)↔FAD C,CC(E)
	PVT 1,E↔CAME 1,V↔GO .+3↔PCW E,E↔GO .+5
	NVT 1,E↔CAME 1,V↔AOJA .+5↔NCW E,E
	CAME E,E0↔AOJA L2↔AOS
	FLOAT↔FDV A,↔FDV B,↔FDV C,
	DAC A,XPP(V)↔DAC B,YPP(V)↔DAC C,ZPP(V)
	GO L1
ENDR VNORM;1/14/73(BGB)----------------------------------------------
⊗
SUBR(QEV,EDGE,VERTEX)		;DISTANCE VERTEX TO EDGE.
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{E,V}
	LAC V,VERTEX↔LAC E,EDGE↔LAC 1,CC(E)
	LAC BB(E)↔FMPR YPP(V)↔FADR 1,0
	LAC AA(E)↔FMPR XPP(V)↔FADR 1,0
	POP2J
ENDR QEV;2/10/73(BGB)________________________________________________

SUBR(QFEV,FACE,EDGE,VERTEX)	;DIRECTED DISTANCE VERTEX TO EDGE.
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{E,V}
	LAC V,VERTEX↔LAC E,EDGE↔LAC 1,CC(E)
	LAC BB(E)↔FMPR YPP(V)↔FADR 1,0
	LAC AA(E)↔FMPR XPP(V)↔FADR 1,0
	PFACE 0,E↔CAME 0,FACE↔MOVNS 1
	POP3J
ENDR QFEV;2/10/73(BGB)_______________________________________________

SUBR(CROSSING,X,Y,EDGE1,EDGE2)
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{TT,XPTR,YPTR,E1,E2}
	LAC E1,EDGE1↔LAC E2,EDGE2
	LAC AA(E1)↔FMPR BB(E2)
	LAC 1,AA(E2)↔FMPR 1,BB(E1)↔FSBR 0,1↔DAC TT
	LAC BB(E1)↔FMPR CC(E2)
	LAC 1,BB(E2)↔FMPR 1,CC(E1)↔FSBR 0,1↔FDVR 0,TT↔DAC@X
	LAC CC(E1)↔FMPR AA(E2)
	LAC 1,CC(E2)↔FMPR 1,AA(E1)↔FSBR 0,1↔FDVR 0,TT↔DAC@Y
	POP4J
ENDR CROSSING;2/10/73(BGB)-------------------------------------------
SUBR(ZDEPTH,FACE,VERTEX)	;ZPP DEPTH.
COMMENT .------------------------------------------------------------
Return AC0 =-1 when vertex is under the face;
Return AC0 = 0 when vertex is above the face;
Return AC1 = ZPP depth = (KK-AA*Xpp-BB*Ypp)/CC .
	ACCUMULATORS{F,V}
	EXCH V,VERTEX↔EXCH F,FACE	;GET ARGS & SAVE ACS.
	LAC 1,KK(F)
	LAC AA(F)↔FMPR XPP(V)↔FSBR 1,0
	LAC BB(F)↔FMPR YPP(V)↔FSBR 1,0
	FDVR 1,CC(F)
	SETO↔CAMG 1,ZPP(V)↔SETZ		;ZPP-OVER > ZPP-UNDER.
	EXCH V,VERTEX↔EXCH F,FACE	;RESTORE ACCUMULATORS.
	POP2J
ENDR ZDEPTH;2/10/73(BGB)---------------------------------------------

SUBR(ZDALT,FACE,X,Y)
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{F}
	LAC F,FACE↔LAC 1,KK(F)
	LAC AA(F)↔FMPR X↔FSBR 1,0
	LAC BB(F)↔FMPR Y↔FSBR 1,0
	FDVR 1,CC(F)↔POP3J
ENDR ZDALT;2/10/73(BGB)----------------------------------------------

	DEFINE TJOINT(Q,V)<CAR Q,2(V)>
	DEFINE TJOIN.(Q,V)<DIP Q,2(V)>
SUBR(WITHIN,FACE,VERTEX)		;WITHIN 2-D PP COORDINATES.
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{F,V,E,E0}
	SAVAC(5)
	LAC F,FACE↔LAC V,VERTEX↔PED E,F↔DAC E,E0
L1:	LAC 1,CC(E)
	LAC BB(E)↔FMPR YPP(V)↔FADR 1,0
	LAC AA(E)↔FMPR XPP(V)↔FADR 1,0
	PFACE 0,E↔CAME 0,F↔MOVNS 1
L2:	JUMPLE 1,L3			;VERTEX OUTSIDE FACE.
	SETQ(E,{ECCW,E,F})
	CAME E,E0↔GO L1
	CALL(LINKED↑,F,V)↔JUMPN 1,L3     ;NO SKIP - VERTEX IS PART OF THIS FACE.
	TESTZ V,JUTBIT+JOTBIT↔GO[
	TJOINT V,V↔CALL(LINKED↑,F,V)
	JUMPN 1,L3↔GO .+1]
	AOS(P)				;SKIP VERTEX WITHIN FACE.
L3:	GETAC(5)
	POP2J
ENDR WITHIN;2/27/73(BGB)---------------------------------------------

SUBR(WITH2D,FACE,X,Y)		;LOCUS WITHIN 2-D PP COORDINATES.
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{F,E,E0}
	SAVAC(4)
	LAC F,FACE↔PED E,F↔DAC E,E0
L1:	LAC 1,CC(E)
	LAC BB(E)↔FMPR Y↔FADR 1,0
	LAC AA(E)↔FMPR X↔FADR 1,0
	PFACE 0,E↔CAME 0,F↔MOVNS 1
L2:	JUMPLE 1,L3			;LOCUS IS OUTSIDE FACE.
	SETQ(E,{ECCW,E,F})
	CAME E,E0↔GO L1
	AOS(P)				;SKIP LOCUS WITHIN FACE.
L3:	GETAC(4)↔POP3J
ENDR WITH2D;BGB 28 APRIL 1974 ---------------------------------------

SUBR(PPROJ,CAMERA,WORLD)
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{B,F,E,V,CAM,E0,X,XX,Y,YY,Z,ZZ}
	LAC B,WORLD↔$TYPE 0,B↔CAIE 0,$WORLD↔POP2J
;CLEAR FACE PZZ & NZZ BITS.
	LAC B,WORLD
I0:	CCW B,B↔CAME B,WORLD↔GO[LAC F,B
I1:	PFACE F,F↔CAMN F,B↔GO I0↔MARKZ F,PZZ+NZZ↔GO I1]

;GET THE CAMERA'S FRAME.
	LAC CAM,CAMERA
	LAC 3(CAM)↔DAC FOCL#		;FOCAL PLANE DISTANCE.
	FRAME CAM,CAM

;FOR ALL THE BODIES OF THE WORLD.
	LAC B,WORLD
L1:	CCW B,B↔CAMN B,WORLD↔POP2J
	MARKZ B,VISIBLE

;FOR ALL THE VERTICES OF EACH BODY.
	LAC V,B
L2:	PVT V,V↔CAMN V,B↔GO L1
	CALL(VPROJ,V,CAMERA)
;DO Z-CLIP MARKING WRT CAMERA CENTERED COORDINATES.
	LAC 0,[JUTBIT+JOTBIT+PZZ+NZZ+FOLDED+VISIBLE+POTENT+7B20]
	ANDCAM 0,(V)		;TURN 'EM ALL OFF.
	MOVSI X,(PZZ)		; + HALFSPACE, BEHIND THE CAMERA.
	MOVN FOCL
	CAMGE ZZ,0		;SKIP WHEN Zcc ≥ -FOCAL.
	MOVSI X,(NZZ)		; - HALFSPACE, INVIEW.
	IORM X,(V)

	PED E,V↔DAC E,E0↔JUMPE E,[
	PFACE F,B↔IORM X,(F)↔GO L1] 		;VERTEX BODY CASE.
MOVEI =30↔DAC TMPCNT# ;PATCH FOR CDT 2/9/75
L3:	PVT 1,E↔CAME 1,V↔GO .+3↔PCW 1,E↔GO L4	   ;AC1 ← ECCW(E,V).
	NVT 1,E↔CAME 1,V↔GO L2 ↔NCW 1,E
L4:	IORM X,(E)
	PFACE F,E↔IORM X,(F)
	NFACE F,E↔IORM X,(F)
	LAC E,1
SOSGE TMPCNT↔GO L2 ;PATCH FOR CDT 2/9/75
	CAME E,E0↔GO L3↔GO L2
ENDR PPROJ;1/14/73(BGB)----------------------------------------------
SUBR(VPROJ,VERTEX,CAMERA)	;VERTEX PERSPECTIVE PROJECTION.
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{B,F,E,V,CAM,E0,X,XX,Y,YY,Z,ZZ,FRM}

;PICKUP ARGUMENTS.
	LAC CAM,CAMERA
	FRAME FRM,CAM
	LAC V,VERTEX

;TRANSLATE VERTEX TO CAMERA LOCUS.
	LAC X,XWC(V)↔FSBR X,XWC(FRM)
	LAC Y,YWC(V)↔FSBR Y,YWC(FRM)
	LAC Z,ZWC(V)↔FSBR Z,ZWC(FRM)

;ROTATE TO CAMERA ORIENTATION.
	LAC XX,X↔FMPR XX,IX(FRM)
	LAC    Y↔FMPR    IY(FRM)↔FADR XX,
	LAC    Z↔FMPR    IZ(FRM)↔FADR XX,

	LAC YY,X↔FMPR YY,JX(FRM)
	LAC    Y↔FMPR    JY(FRM)↔FADR YY,
	LAC    Z↔FMPR    JZ(FRM)↔FADR YY,

	LAC ZZ,X↔FMPR ZZ,KX(FRM)
	LAC    Y↔FMPR    KY(FRM)↔FADR ZZ,
	LAC    Z↔FMPR    KZ(FRM)↔FADR ZZ,

;PERSPECTIVE TRANSFORMATION.
;XPP(V) ← SCALEX * XCC/ZCC.	SCALEX = -FOCAL/PDX.
;YPP(V) ← SCALEY * YCC/ZCC.	SCALEY = -FOCAL/PDY.
;ZPP(V) ← SCALEZ      /ZCC.	SCALEZ = -FOCAL/PDZ.
;ZPP(V) IS POSITIVE WHEN VERTEX IS INVIEW.   ←←← NOTA BENE.

	MOVM ZZ↔CAMGE[1E-7]↔LAC ZZ,[1E-7]	;AVOID ZERO DIVIDE.
	FMPR XX,-3(CAM)↔FDVR XX,ZZ↔DAC XX,XPP(V)
	FMPR YY,-2(CAM)↔FDVR YY,ZZ↔DAC YY,YPP(V)
	LAC   Z,-1(CAM)↔FDVR  Z,ZZ↔DAC  Z,ZPP(V)
	SETZM 7(V)↔POP2J	;CCW IS FOR SORT WINDOW V-LISTS.

ENDR VPROJ;(BGB)-----------------------------------------------------
SUBR(UNPROJECT,VERTEX,CAMERA)
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{V,C,R,X,Y,Z,XX,YY,ZZ}

;PICKUP ARGUMENTS.
	LAC V,VERTEX
	LAC C,CAMERA
	FRAME R,C

;UNDO PERSPECTIVE.
	LAC  Z,-1(C)↔FDVR Z,ZPP(V)		;SCALEZ.
	LAC  Y,YPP(V)↔FMPR Y,Z↔FDVR Y,-2(C)	;SCALEY.
	LAC  X,XPP(V)↔FMPR X,Z↔FDVR X,-3(C)	;SCALEX.

;ROTATE BY TRANSPOSE OF CAMERA ORIENTATION.
	LAC XX,X↔FMPR XX,IX(R)
	LAC    Y↔FMPR    JX(R)↔FADR XX,
	LAC    Z↔FMPR    KX(R)↔FADR XX,

	LAC YY,X↔FMPR YY,IY(R)
	LAC    Y↔FMPR    JY(R)↔FADR YY,
	LAC    Z↔FMPR    KY(R)↔FADR YY,

	LAC ZZ,X↔FMPR ZZ,IZ(R)
	LAC    Y↔FMPR    JZ(R)↔FADR ZZ,
	LAC    Z↔FMPR    KZ(R)↔FADR ZZ,

;TRANSLATE TO CAMERA LOCUS.
	FADR XX,XWC(R)↔DAC XX,XWC(V)
	FADR YY,YWC(R)↔DAC YY,YWC(V)
	FADR ZZ,ZWC(R)↔DAC ZZ,ZWC(V)
	POP2J

ENDR UNPROJECT;1/14/73(BGB)------------------------------------------
SUBR(FACOEF,BF)		;FACE COEFFICIENTS. BF>0 WC, BF<0 PP.
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS {Q2,Q3,E,V1,V2,V3,ABC,F,ARG,E0}
	FOR @% Qε{XYZ}{FOR @$ N←1,3{		;DEFINE X1,Y1,Z1...
	DEFINE Q%$N<Q%WC(V$N)>↔}}
;FOR ALL THE FACES OF EACH BODY.
	MOVM F,BF↔LAC ARG,(F) 			;ORIGINAL ARG TYPE.
	TLNN ARG,(BBIT)↔GO L2
L1:	PFACE F,F↔TEST F,FBIT↔POP1J

;FIRST THREE VERTICES CCW ABOUT THE FACE.
L2:	PED E,F↔DAC E,E0
L3:	SETQ(V1,{VCW,E,F})
	SETQ(V2,{VCCW,E,F})
	SETQ(E,{ECCW,E,F})
	SETQ(V3,{VCCW,E,F})

;FLG TRUE FOR PERSPECTIVE PROJECTED FACOEF.
	SKIPG BF↔GO[ADDI V1,7↔ADDI V2,7↔ADDI V3,7↔GO .+1]

;KK(F) ← X1*(Z2*Y3-Y2*Z3) + Y1*(X2*Z3-Z2*X3) + Z1*(Y2*X3-X2*Y3).
	LAC 1,Z2↔FMPR 1,Y3↔LAC Y2↔FMPR Z3↔FSBR 1,0↔FMPR 1,X1↔LAC 2,X2↔FMPR 2,Z3
	LAC Z2↔FMPR X3↔FSBR 2,0↔FMPR 2,Y1↔FADR 1,2↔LAC 3,Y2↔FMPR 3,X3
	LAC X2↔FMPR Y3↔FSBR 3,0↔FMPR 3,Z1↔FADR 1,3↔DAC 1,KK(F)
	MOVMS 1↔CAML 1,[1.0]↔GO L4	;SKIP KK TOO SMALL.
	CAME E,E0↔GO L3

;AA(F) ← (Z1*(Y2-Y3) + Z2*(Y3-Y1) + Z3*(Y1-Y2)).
L4:	LAC 1,Y2↔FSBR 1,Y3↔FMPR 1,Z1↔LAC 0,1
	LAC 1,Y3↔FSBR 1,Y1↔FMPR 1,Z2↔FADR 0,1
	LAC 1,Y1↔FSBR 1,Y2↔FMPR 1,Z3↔FADR 0,1↔DAC AA(F)↔FMPR↔DAC ABC

;BB(F) ← (X1*(Z2-Z3) + X2*(Z3-Z1) + X3*(Z1-Z2)).
	LAC 1,Z2↔FSBR 1,Z3↔FMPR 1,X1↔LAC 0,1
	LAC 1,Z3↔FSBR 1,Z1↔FMPR 1,X2↔FADR 0,1
	LAC 1,Z1↔FSBR 1,Z2↔FMPR 1,X3↔FADR 0,1↔DAC BB(F)↔FMPR↔FADRM ABC

;CC(F) ← (X1*(Y3-Y2) + X2*(Y1-Y3) + X3*(Y2-Y1)).
	LAC 1,Y3↔FSBR 1,Y2↔FMPR 1,X1↔LAC 0,1
	LAC 1,Y1↔FSBR 1,Y3↔FMPR 1,X2↔FADR 0,1
	LAC 1,Y2↔FSBR 1,Y1↔FMPR 1,X3↔FADR 0,1↔DAC CC(F)↔FMPR↔FADRM ABC

;NORMALIZE.
	CALL(SQRT↑,ABC)↔MOVSI(<1.0>)↔FDVR 0,1
	FMPRM AA(F)↔FMPRM BB(F)↔FMPRM CC(F)↔FMPRM KK(F)
	TLNN ARG,(BBIT)↔POP1J↔GO L1
ENDR FACOEF;1/14/73(BGB)---------------------------------------------

SUBR(WITH3D,FACE,X,Y,Z)		;TEST FOR LOCUS WITHIN FACE 3D.
COMMENT .-----------------------------------------------------------.
	ACCUMULATORS{FLG,V,E,F,DX1,DY1,DZ1,Q1,DX2,DY2,DZ2,Q2,E0}
	
;SELECT COMPONENT BY LARGEST FACE COEFFICIENT.
	LAC F,FACE
	MOVM 1,AA(F)
	MOVM 2,BB(F)
	MOVM 3,CC(F)
	MOVEI C0↔CAMG 1,2↔GO[
	MOVEI C1↔CAMG 2,3↔MOVEI C2↔GO .+3]
		CAMG 1,3↔MOVEI C2↔DAP CASE

;FIRST EDGE OF THE FACE.
	SETOM FLG
	PED E,F↔DAC E,E0↔SETQ(V,{VCW,E,F})
	LAC DX2,XWC(V)↔FSB DX2,X
	LAC DY2,YWC(V)↔FSB DY2,Y
	LAC DZ2,ZWC(V)↔FSB DZ2,Z

L1:	LAC DX1,DX2
	LAC DY1,DY2
	LAC DZ1,DZ2
	LAC Q1,Q2

;NEXT EDGE OF THE FACE.
	SETQ(V,{VCCW,E,F})
	SETQ(E,{ECCW,E,F})
	LAC DX2,XWC(V)↔FSB DX2,X
	LAC DY2,YWC(V)↔FSB DY2,Y
	LAC DZ2,ZWC(V)↔FSB DZ2,Z

;COMPUTE A COMPONENT OF THE CROSS-PRODUCT.

CASE:	GO
C0:	LAC 0,DY2↔FMP 0,DZ1↔LAC 1,DY1↔FMP 1,DZ2↔GO C3
C1:	LAC 0,DX1↔FMP 0,DZ2↔LAC 1,DX2↔FMP 1,DZ1↔GO C3
C2:	LAC 0,DX2↔FMP 0,DY1↔LAC 1,DX1↔FMP 1,DY2
C3:	FSB 0,1↔DAC Q2
	JUMPE 0,L3		;LOCUS IS ON A FUCKING EDGE !

;DETECT SIGN CHANGE.

	AOJE FLG,L2		;JUMP ON FIRST TIME THRU.
	XOR Q1↔JUMPL POP4J.	;NO SKIP RETURN FALSE.
L2:	CAME E,E0↔GO L1
	AOS(P)↔POP4J		;SKIP RETURN TRUE - LOCUS IS WITHIN.
L3:	LAC DX1↔FMP DX2			;COSINE.
	LAC 1,DY1↔FMP 1,DY2↔FAD 0,1
	LAC 1,DZ1↔FMP 1,DZ2↔FAD 0,1
	SKIPGE↔AOS(P)↔POP4J		;SKIP RETURN TRUE - LOCUS IS WITHIN.
ENDR WITH3D;3/7/73(BGB)----------------------------------------------

SUBR(SOLANG,VERTEX)	DIHEDRAL ANGLE AT A PIERCING VERTEX.
COMMENT .-----------------------------------------------------------.
	EXTERN ACOS,DISTANCE,TWOPI
	ACCUMULATORS{F,V}

	LAC 1,VERTEX↔DAC 1,V0
	PED 1,1↔DAC 1,E
	SETQ(F1,{FCCW,E,V0})↔SETQ(V1,{OTHERV↑,F1,V0})
	SETQ(F2,{FCW,E,V0})↔ SETQ(V2,{OTHERV,F2,V0})

	CALL(DISTANCE,V1,V0)↔PUSH P,1		;L1
	CALL(DISTANCE,V2,V0)↔PUSH P,1		;L2
	CALL(DISTANCE,V1,V2)↔FMPR 1,1↔MOVNS 1	;L3

;ANGLE ← ACOS((L1*L1 + L2*L2 - L3*L3)/(2*L1*L2)).
	POP P,2↔POP P,3
	LAC 2↔FMPR 3↔FSC 1
	FMPR 2,2↔FMPR 3,3
	FADR 1,2↔FADR 1,3
	FDVR 1,0
	CALL(ACOS,1)↔PUSH P,1

	LAC V,V2↔LAC F,F1
	LAC 0,XWC(V)↔FMPR 0,AA(F)
	LAC 1,YWC(V)↔FMPR 1,BB(F)↔FADR 0,1
	LAC 1,ZWC(V)↔FMPR 1,CC(F)↔FADR 0,1
	POP P,1
	CAML KK(F)↔POP1J↔MOVNS 1
	FADR TWOPI↔POP1J	;REFLEX ANGLE.
DECLARE{V0,V1,V2,E,F1,F2}
ENDR SOLANG;3/23/73(BGB)---------------------------------------------
END
EUCLID.FAI  -  EOF.