!S1ModDef.f95                         Stereo-3D Simulation Environment Vsn:1.00
!2025.05.24.1840cdt- Variable Modules of the visual simulation environment.

!            Author- Jeffrey M. Setterholm, Lakeville,MN 55044 USA
!         IP Status- Free source code (e.g.: post copyright)
!
!          Computer- "T3"/Dell Precision T3500/Intel i5 E5520/Win10Pro-21H2
!                     ^name ^Mfgr.Id           ^chipset       ^OS 
!                    /Absoft Pro Fortran 21.0.2/GeForce GTX 1050/f90gl~Glut3.7
!                     ^compiler ~Fortran 95     ^graphics card   ^graphics

!    f90gl bindings- public domain; see "https://math.nist.gov/f90gl/"

!Disclaimer:
! ***************************************************************
! **********   Individual cognition is always flawed,  **********
! **********         including yours and mine.         **********
! **********                 - So: -                   **********
! **********       Use this code at your own risk.     **********
! ***************************************************************

!Table of Contents: ...use to search...
! Module OpenGLRec          !Ref: OpenGL GL/GLU/GLUT Documentation
! Module TaskDef            !Project/Context
! Module ioDef              !Files,Units,TimeStamp,Selfies,Flags
! Module ScreenDef          !screen & colors
! Module KeyboardDef        !Keyboard
! Module ModuleDef          !Mo Module
! Module ViewDef            !View bounds->[0.,+1.]->[extent]Destination
! Module ModelDef           !Modelview Matrix Generation
! Module SimDef             !Simulation F9-F12
! Module HelpDef            !Help (a text block)
! Module AppsDef            !User Apps F1-F8
! Module F3dvDef            !File .3dv data
! Module BreakPtDef         !BreakPoint & Scrolling
! Module UseAllBbDef        !Contents

!---------------------------------------------------------------------------7 9
Module OpenGLRec
!use OpenGLRec          !Ref: OpenGL GL/GLU/GLUT docs            JMS 2020.06.30
 use opengl_gl
 use opengl_glu
 use opengl_glut
!Contains
End Module OpenGLRec
!---------------------------------------------------------------------------7 9
Module TaskDef
!use TaskDef   ,only: & !Project/Context                         JMS 2020.06.30
 !--Environment ID:
  character::EnvBanner*22   ='Sn3D-Environment'
  character::EnvVersion*22  ='2025.05.24 vsn 1.0'
 !--Executable  ID  (Re)Define in Main &/or .nml to agree with project options:
  character::ExeBanner*58   ="Sn3D__-"   !(left side,1st line)
  character::ExeName*22     ='Sn3D.exe'
  character::ExeVersion*22  ='2025.05.24 vsn 1.0'
 !--Analyst info             Set in "Sn3D.nml":
  character::Analyst(     0:8)*35!="  Jeff Setterholm"    !Your info. here
  character::Phone(       0:8)*35!=   "(___) ___-____"
  character::Street(      0:8)*35!=" 8095 230th St. E."
  character::CityStateZip(0:8)*35!="Lakeville, MN 55044"
  character::IPSummary(   0:8)*35!="   IP: ________"      !of your app
 
!----For Screen/Keyboard traceability in S_*.f95\Subroutine SK():
!        "When OpenGL goes South... it helps to know where."
!     Application-specific groups (e.g. files) of subroutines:       2022.04.15
  integer(4)   ::jGroups =   18     !# of groups
  character(16)::jGroupName(0:19) & !Group name(s)
                              = (/ '                ' &   !un-#'d
                                  ,'S1ModDef.f95    ' &   ! 1
                                  ,'S2ModCallbacks.f' &   ! 2
                                  ,'S3Main.f95      ' &   ! 3
                                  ,'S4Callbacks.f95 ' &   ! 4
                                  ,'S5Screen.f95    ' &   ! 5
                                  ,'S6View8.f95     ' &   ! 6
                                  ,'S7Motion7.f95   ' &   ! 7
                                  ,'S8Help.f95      ' &   ! 8
                                  ,'S9Font.f95      ' &   ! 9
                                  ,'-unspecified-   ' &   !10
                                  ,'S-11AppF1.f95   ' &   !11
                                  ,'S-12AppF2.f95   ' &   !12
                                  ,'S-13AppF3.f95   ' &   !13
                                  ,'S-14AppF4.f95   ' &   !14
                                  ,'S-15AppF5.f95   ' &   !15
                                  ,'S-16AppF6.f95   ' &   !16
                                  ,'S-17AppF7.f95   ' &   !17
                                  ,'S-19AppF8.f95   ' &   !18
                                  ,'-unlisted.f95   '  /)
!                                       ^= #jGroups+1
  integer(4)::jNoWrite != 1 :can`t write files,e.g.running from a CD 2022.04.18
!                       = 0 :can   write files

!Contains
End Module TaskDef
!---------------------------------------------------------------------------7 9
Module ioDef
!use ioDef              !Files,Units,TimeStamp,Selfies,Flags     JMS 2023.09.02
 !--Filenames,nml&refresh:
  character::ExeFileOut*35 !='RubikVis-out.txt'  !.exe- output file  (If any)
  character::ExeFileIn*35  !='RubikVis-init.txt' !    - input  file
  character::EnvNml*79    !="Sn.nml"            !Environ- .nml file
  character::EnvIni*79    !="Sn.ini"            !       - .ini file
 !Each app can have its own .nml & .ini files. The namelist datae
 !  are all imported at the beginning of execution after reading Sn.nml
 !  & before transitioning to OpenGL control.
  character::UserNml(8)*79 =char(0) !"RubikVis.nml"!    - .nml
  character::UserIni(8)*79 =char(0) !"RubikVis.ini"!User- .ini file
  integer(4)::Uupdate   !U-key flag to re-read updated .nml files.
 !--Unit#'s & timestamp
  integer(4)::Ur =11    !Unit#- to read various input files.
  integer(4)::Us = 6    !     - write to- screen    - on
  integer(4)::Ut!=13    !     = 13 all writes to ASCII file ExeFileOut, however
                        !  ...= Us        - when ExeFileOut open fails
  integer(4)::Uread=12  !     - 12- for user use in apps
  integer(4)::Uwrite=14 !    = 14- (set =13 when not in use.)
  integer(4)::Uselfie=10      !For exporting selfies to .bmp files
  character::DaTimeLabel*18  !Runtime clock

  character ::DaTimeLabel22*22  !Runtime clock

 !Timer(s):
  integer(4)::JulianDay
  real(8)   ::DaySecond

 type ::  TimeRec;sequence                                          !2023.07.16
  integer(4)   ::nClock  !Clock# (0:30)
  integer(4)   ::V(8)  !Output of: date_and_Time(values=V)
                !V( ) = 1:iYear, 2:iMonth, 3:iDay, 4:Utc time offset(if any)
                !      ,5:iHour, 6:iMin  , 7:iSec, 8:imSec
                !
  character(22)::cDaT22   !Character string:                24->22   2023.08.22
  integer(4)   ::JDay     !Julian Day
  real(8)      ::Sec      !Day second... millisecond resolution
 end type TimeRec
 type(TimeRec)::DaT       !Current Date & Time- computed by: Jdate20(DaTime)
 type(TimeRec)::DaTo(0:30)!30 separate clocks -   nRunSec(nClock,RunSecs,iW)

 !--variables of Pi16Eval(), the Pi value generator:                 2025.04.30
  real(16)  ::Pi16   !Pi- returned value
  integer(4)::ModePi !Compautation mode:
                     !<=0 :returns Pi16
                     != 1 :use Wikipedia's series (2025)
                     != 2 :use Spiegel's series   (1968)
  integer(8)::IterPi !Number of iterations of the series  [1 -to- 10 trillion]

 !--Export now:
  integer(4)::Up      !!Unit#=  0 - usually off. usage: if(Up>0) write(Up,...)
                      !      = Us- for one iteration-  <- press key:"p"
                      !      = Ut-                  -  <-          :"P"
  integer(4)::UpVerb=0!      = 0: Up- doesn't expound on internal ops.
                      !      =+1:   - verbose about DoF's in play
  integer(4)::NowView=1!Toggles the screen-viewing of details- via'vV'
  integer(4)::NowPrint!=0 usually; during one iteration...
                      !=1 by pressing key: 'p' :fp=fpt    ->.txt
                      !=2                : 'P' :fp=stdout ->screen
  integer(4)::DepthSelfie !Toggle the "`" key to display a screen depth map.
 !--File access flags:
  logical  ::LExists  !File existence flag
  integer(4)::iAlloc  !Array allocation flag =0:success
 !--Teapot:
  integer(4)::iTeapot=4 !Use: Tt: -draws the GLUT Teapot eight ways.

!Namelist interface to TweakRec - for runtime reconfiguration of the .exe:

!NAMELIST / SnNml /  ExeFileIn, ExeFileOut           &
!                   ,UserIni  , UserNml              &
!                   ,ExeBanner, ExeName, ExeVersion  &
!                   ,Ut
!Contains
End Module ioDef
!---------------------------------------------------------------------------7 9
Module ScreenDef
!use ScreenDef          !screen & colors                         JMS 2021.03.08
 !--Screen dimensions:
  integer(4)::xWindowFull,yWindowFull !Screen- Pixels hor. & ver.
  integer(4)::xWindowMM  ,yWindowMM   !      - mm     hor. & ver.
 !--Size,ratio,OrthoVecs:
  real(8)   ::PixelsPerCM=0.d0        !      - Pixels per cm     = 37.50 for T-2
  real(8)   ::MagFactor     !Screen mag= yWindowFull/(PixelsPerCM*5.08)
  real(8)   ::xyWindowRatio != xWindowFull / yWindowFull           typically >1.
  real(8)   ::vScrnHVD(2,3) !...defined in ProjOrtho      built on xyWindowRatio
 !--Fullscreen,color,ID:
  integer(4)::iFullScreen
  integer(4)::iScrnColor
  integer(4)::WinId
 !--Palette -Colors3D:   incoming color override (e.g. for Red/Cyan 3D):
  integer(4)::ForceRGBA   ! >0: use Colors3D(ForceRGBA)
                         ! =0: use Colors3D(   nCol  )
                         ! <0: force ColorRGBA=Env.ColorRGBA[4]
  real(4)   ::ColorRGBA(4)!Forced color components, each in: [0.,1.]
                         !e.g. "Red" is {1.,0.,0.,1.}, "Cyan"is {0.,1.,1.,1.}
                         !  ... sets the (Red,Breen,Blue,Alpha) components
 !--Screen text placement & raw location:
  integer(4)::lCharX     ,lCharY      !<- Values set in GlutHandoff
  integer(4)::nCharOffset=0           !Split screens need a character offset
  integer(4)::nCharMaxX  ,nCharMaxY
  integer(4)::nCharCenX  ,nCharCenY   !For aligning text on arbitrary screens
  real(8)   ::cWidth     ,cHeight
  real(8)   ::xPrint, yPrint, zPrint

 !--ScreenSide:
  integer(4)::SideInit           !=0:uninitialized; =1:initialized.
  integer(4)::Side               !-1:Left, 0:full screen, +1:Right
  integer(4)::nCharOffsetS(-1:1)
  integer(4)::nCharMaxXS(-1:1)
  integer(4)::nCharCenXS(-1:1)

 !--^K:Keys redirector:
  integer(4)::ctlKbd=0 !Ctl-K(#11) =0:normal        Toggled in cbKeyboard 
                      !           =1:keyboard reader, except ctl-Q quits
 !--SubWindow
  integer(4)::SubWinId
  integer(4)::WId

!Contains
End Module ScreenDef
!---------------------------------------------------------------------------7 9
Module KeyboardDef
!use KeyboardDef        !Keyboard                                JMS 2020.06.30
 !--Keyboard primitives:
  character::KbdKeyChar*1  !was: unsigned char KbdKey !<- K's are upper case
  integer(4)::KbdKeyIn      !not zeroed out  if  used- & displayed
  integer(4)::KbdKey        !    zeroed out once used-
  integer(4)::ArrowKeyIn    !not zeroed out  if  used
  integer(4)::ArrowKey      !    zeroed out once used-
  integer(4)::nKpress=0     !number of Keypresses
  integer(4)::KeyHist(3,3)  !Key press(1:key#,type[1:kbd,2:Arrow],3:modifier|
  integer(4)::NumLockOn=1   !An attempt to detect NumLock-off
  real(8)   ::DtoR !Degrees-to-Radians conversion constant.
  integer(4)::iKeyMods
!Contains
End Module KeyboardDef
!---------------------------------------------------------------------------7 9
Module MouseDef
!use MouseDef           !Mouse                                   JMS 2020.06.30
 use OpenGLRec,only:glcint  !The OpenGL GL,GLU,GLUT interface
!use MouseDef   ,only: &  !Mouse
!     MouseScreenh,iMouse7DoF                              &
!    ,Mouse2DRec,mbID,PresPrevRec,PpX,PpY,ManChanRec       &
!    ,MouseInit,iMouseButton,MouseDirect,MouseDirectPrev   &
!    ,nMpress,mdHist,MXY,MXYdel                            &
!    ,mdTot,Mouse,MouseU,Mouse0,MChan,MChanX,MChanY,MChan0
!--------------------------------------
 !--Mouse control of 7DoF:
  integer(4):: iMouse7DoF=0  !Toggle: =0:control- PoI    'm' key
                            !        =1:       - FS7
 !--Mouse 3D screen coordinates:
  real(4)   ::MouseScreenh(4)

!--Raw mouse 2D positional output:
 type ::  Mouse2DRec
  integer(kind=glcint):: iX ,iY                                  ![0:ScreenPix]
  integer(4)           ::md        !Record's MouseDirect index
  integer(4)           ::mcx ,mcy  !X:MChan(#) & Y:MChan(#)
  character*6         ::ID        !Button's identifier
 end type Mouse2DRec
 !--Mouse Button ID's:
  character*6::mbID(12)=(/ "LMB-up","LMB-dn" & !iMouse7DoF=1: mouse 7DoF
                          ,"MMB-up","MMB-dn" &
                          ,"RMB-up","RMB-dn" &
                          ,"L-up  ","L-down" & !iMouse7DoF=0: user discretion
                          ,"M-up  ","M-down" &
                          ,"R-up  ","R-down"  /)
!--Track Present & Previous 1D channel activity:
 type ::  PresPrevRec
  integer(4)::iPix   !current 1D screen pixel value
  integer(4)::nChar  !Screen character y:column# or x:row# of .iPix
  integer(4)::iUsed  !usage status
                    !=-2 key/button remains N/A
                    !=-1 key/button just N/A
                    !=+1 key/button just applicable
                    !=+2 key/button remains applicable
                    !=+3 iPix value has changed
  integer(4)::Iter   !counter- iteration
  real(8)   ::RunSecs!       - seconds- millisecond resolution.
 end type PresPrevRec
 type(PresPrevRec)::PpX(2),PpY(2)

!--Mouse 1D Channel rescale & direct:
!--1D Manual Channel Record:
 type ::  ManChanRec
  integer(4)::mc          !Record's MChan index
  integer(4)::iDeltaPix   !Delta iPix in the most recent activation.
  real(8)   ::r01    !                                           [ 0.:   1.    ]
  real(8)   ::rm11   !                                           [-1.:   1.    ]
  integer(4)::i7DoF       !Target 7DoF variable XyzRpyS(i7Dof), or =0 for none.
  integer(4)::ie          !=1: interior
                         !=2: exterior
  real(8)   ::V           !Numerical value
  integer(4)::Locked      !0:unLocked, 1:Locked (w.r.t. Mouse changes?)
  integer(4)::iX1Y2       !Applicable axis: =1:X|column, =2:Y|row
  integer(4)::iPixMax     !Range of Pp().iPix value  [1:iPixMax]
  integer(4)::mdParent    !part of ____, e.g. a mouse button pair.
 type(PresPrevRec)::Pp(2)
  real(8)   ::Sensitivity !DoF value change for iDeltaPix = +1
  character::ID*8        !channel use identifier.
 end type ManChanRec

 !--Mouse button states:
  integer(4)::MouseInit =0    !=1: when Mouse callbacks have been initialized.
  integer(4)::iMouseButton    !0:Left  1:Middle  2:Right 
                                    !( =1 x - unavailable on my computer. )
  integer(4)::iMouseState     !0:down    1:up

 !--The button and state yield 6 possibilities:
  integer(4)::MouseDirect     !=2*iMouseButton-iMouseState+2 [1, 2,x,x, 5,  6]
                             !  odds "up", evens "down"      Left      Right
  integer(4)::MouseDirectPrev !Previous iteration's value of MouseDirect
  integer(4)::nMpress=0       !number of mouse button changes
  integer(4)::mdHist(3)       !MouseDirect value History
                             !1:most recent ->2:prev->3:prev
  integer(4)::MXY( 4,3)       !Mouse (X|Y|md|IterTotal,history 1:3)
  integer(4)::MXYdel(4)       !Mouse (X|Y|md|IterTotal)

  integer(4)       ::mdTot=12 !Total number of mouse button states.
  type(mouse2DRec)::Mouse(12)!2D positions on the screen.
  type(Mouse2DRec)::MouseU   !=Mouse(MouseDirect)- read only
  type(Mouse2DRec)::Mouse0   !Mouse()- undefined.

 !--Channel information processing:
 type(ManChanRec)::MChan(24) !(LuX,LuY,LdX,LdY,x,x,x,x,RuX,RuY,RdX,RdY
                             !                ,TBDuX,TBDuY,TBDdX,TBDdY)
 type(ManChanRec)::MChanX    !MouseU's Mchan- X- read only
 type(ManChanRec)::MChanY    !              - Y-
 type(ManChanRec)::MChan0    !MChan() undefined

!Contains
End Module MouseDef
!---------------------------------------------------------------------------7 9

Module ViewDef
!use ViewDef       !View bounds->[0.,+1.]->[extent]Destination   JMS 2020.06.30
!use ViewDef,only: ThreePhase,Key,V,jVG,VisGeom
 implicit none

!--View seq. each call:  *** Apps manage themselves in three phases: ***
  integer(4)::ThreePhase      !=1 Initialization & background number crunching.
                             !=2 Update variables & display 2D information
                             !=3 Redraw the 3D graphics part of the app.
  integer(4)::ThreePhaseEnder !>0 terminates the present callback from OpenGL
!--
!-- Runtime initial values: 
  real(8)   ::UnitCube0(0:8) & !Z0,D ,E ,N ,F ,L ,R ,T ,B  !Unit Cube
            =(/ 1.0d0,24.0d0,1.2d0,-10.0d0,10.0d0,-10.4d0,10.4d0,-6.5d0,6.5d0/)
  real(8)   ::Dv0(1:6)         !         N2,F2,L2,R2,T2,B2 !Destination rescale

 !--Frustum parameters in GlutHandoff:
  real(8)   ::FrustNom( 0:8) & != Z,D,E,N,F,L,R,T,B  <-Nominal values
            =(/ 1.0d0,24.0d0,1.2d0,-10.0d0,10.0d0,-10.4d0,10.4d0,-6.5d0,6.5d0/)
!           =(/-1.0d0,24.0d0,1.2d0,-10.0d0,10.0d0,-12.4d0, 8.4d0,-8.5d0,4.5d0/)
!              ^ "zoom" <0. disables L,R,T,B autofit by OpenGL         20200419
!                Note: Only Frustnom has a (0) coefficient for Z.

!\\\\\\\\
 type ::  VisGeomKeyRec !Vision Geometry Keys & Flags: "Key._"
!--Viewing gear target:
  integer(4):: &
        SplitScreen!=-1: Right|Left split- screen    + crossed-eyes
                   != 0: Full-screen view- screen    + red|cyan glasses
                   !=+1: Left|Right split- cellphone + head-mounted viewer
!--Viewing Mode:
  integer(4)::VuMode!=-1: OpenGL ~raw screen coordinates
                   != 0: Orthographic
                   !=+1: Perspective
                   !=+2: Stereo 3D
!--Eye's view being drawn:
  integer(4)::iEye  !=-1: Left
                   != 0: Monocular
                   !=+1: Right
!--Unit cube bounds:
  integer(4)::Cube  != 0: Default screen volume
                   !=+1: User pre-defined UnitCube0(0:8)
                   !=+2: Pixel-driven volume
                   !=+3: Other user defined volume (TBD)
!--Unit cube's input scale:
  integer(4)::Scaler!= 0: L,R,T,& B are redefined by screen's- centimeters
                   !                           & Key.cScaler="cm."
                   !=+1: L,R,T,& B are redefined by screen's- inches
                   !                           & Key.cScaler="in."
                   !=+2: Users D,E,N,F,L,R,T, & B passthrough
                   !                         &eg Key.cScaler="Furlongs" a12 max
                   !     Setting E=D/20. provides comfortable 3D viewing.
  character:: &
         cScalar*12 ="Not defined."

!--Destination (screen|pixels|printout|etc.) bounds:
  integer(4)::Dest  != 0: Default screen output
                   !=+1: User pre-defined Rv0(1:6)
                   !=+2: Default Pixel output
                   !=+3: User defined output (TBD)
!--Transforms no-morph:
  integer(4)::SFSOut!= 0: FS(+X,+Y,+Z,W) -> OpenGL(+Z,+X,-Y,W),
                   !       a left-handed coordinate system which uses
                   !       destination values:(/ -1.,+1.,-1.,+1.,-1.,+1./)
                   !=+1: Retain "Standard Flight Simulation Coordinates".
!--Full-screen 3D color control:
  integer(4):: &
         SplitColor!= 0: Passthrough- full color (here: 8bit RGB)
                   !=+1: Left:Red , Right:Cyan (3D background- black)
                   !=+2:     :Cyan,      :Red  (             - white)
                   !   & negate for grayscale-before-color-splitting.
 end type VisGeomKeyRec 
  type(VisGeomKeyRec)::Key,KeyReset
!////////

  integer(4)::jVG !Vision geometry 2nd index for: Uv(,_),Rv(,_),Fh(,_) & Fo(,,_)
                 != -2: Divide L,R,T,B by Z0. Implicitly Z0=1.
                 !      both the baseline & the clipping planes values.
                 !  -1: Left Eye's view
                 !   0. Monocular view
                 !  +1: Right eye's view

!\\\\\\\\
 type ::  VisionGeometryRec !Vision Geometry variables: "V._"
 !--Internalized keys & Flags
  type(VisGeomKeyRec)::Key

 !-----The unit cube normalizes the volume that you want to visualize:
  real(8)   :: Mult0 !Initial multiplier of unit cube values; ==1. is a no-op.

 !--Unit Cube's 8DoF values:                                     & Note#1 below
  real(8)   :: D! 1 X: Depth >0.    + is forward
  real(8)   :: E! 2 Eye +Y (right) offset  (3D:>0., 2D:=0.) >= 0. initially
  real(8)   :: N! 3    Near  <0.,>-D   limited by [E,(R-L)] >=-D
  real(8)   :: F! 4    Far   >0.       limited by [E,(R-L)] >  N
  real(8)   :: L! 5 Y: Left         + is  right    =Lnom/Z0
  real(8)   :: R! 6    Right >Left                 =Rnom/Z0
  real(8)   :: T! 7 Z: Top          + is   down    =Tnom/Z0
  real(8)   :: B! 8    Bottom >Top                 =Bnom/Z0
 !--Intermediate values: homogeneous/orthographic  ~Algebra 1+   & Note#1 below
 !                       homogeneous/projective/3D - genuinely clever
  real(8)   ::Mx! 9 f(N,F)-slope       +X:into 
  real(8)   ::Bx!10       -intercept  ~  Mx*X+Bx -> X - [0.,1.] in view
  real(8)   ::My!11 f(L,R)-slope       +Y:right
  real(8)   ::By!12       -intercept  ~  My*Y+By -> Y -
  real(8)   ::Mz!13 f(T,B)-slope       +Z:down
  real(8)   ::Bz!14       -intercept  ~  Mz*Z+Bz -> Z -
 !--Corresponding Cube vector:
  real(8)   ::Cv(14,-2:1) !=(/D,E,N,F,L,R,T,B,Mx,Bx,My,By,Mz,Bz/)
                         !   1 2 3 4 5 6 7 8  9 10 11 12 13 14
                         !  | ~user defined |----computed-----|
!--Unit Cube names (for printouts):
  character::UcId(-2:1)*40

!--Clipping planes, in Flight Simulation coordinates:
  real(8)   ::Clip(4,8)   !Defined using Uv(1:8,-2)

 !--Destination- display 6DoF rescale values:
  real(8)   ::N2! 1 depth/into- Near                              & Note#1 below
  real(8)   ::F2! 2           - Far
  real(8)   ::L2! 3 lateral   - Left
  real(8)   ::R2! 4           - Right
  real(8)   ::T2! 5 vertical  - Top
  real(8)   ::B2! 6           - Bottom
 !--Intermediate values:       [0.,1.]-> y=m*x+b -> [ whatever]  & Note#1 below
  real(8)   ::Mi! 7 f(N2,F2)-slope       depth/into 
  real(8)   ::Bi! 8         -intercept -> Mi*X+Bi -> [iwhatever]
  real(8)   ::Mh! 9 f(L2,R2)-slope       lateral
  real(8)   ::Bh!10         -intercept -> Mh*Y+Bh -> [hwhatever]
  real(8)   ::Mv!11 f(T2,B2)-slope       vertical
  real(8)   ::Bv!12         -intercept -> Mv*Z+Bv -> [vwhatever]
 !--Corresponding Destination vector:
  real(8)   ::Dv(12,-2:1) !=(/N2,F2,L2,R2,T2,B2,Mi,Bi,Mh,Bh,Mv,Bv/)
                         !   1  2  3  4  5  6  7  8  9  10 11 12
                         !  |  ~user defined  |----computed-----|

!--Homogeneous frustums:
  real(8)   :: Fh(4,4,-1:1)!'The Frustum matrices in FS coordinates.'.
            ! Fh(_,_, -1 ) view- left  eye- with or /wo splitting.
            ! Fh(_,_, +1 )     - right eye-
            ! Fh(_,_,  0 ) no screen splitting,& no eye offset (E=0.)
  integer(4)::iFh(    -1:1)!Flags Fh(_,_,*) use =+1:computed.
                          !                    = 0:undefined.
  real(8)   :: Fo(4,4,-1:1)!'The output frustums in the requested coordinates.
                          !  E.g.: the OpenGL version.

 !--Metrology variables:
  integer(4)::iSystemMFP    !=1:Meters; =2:Feet; +3:Pixels E.g.: = 1
  real(8)   ::MfpScaleFactor!Scale factor of iSystemMFP       &  = 1.d-2
  character::MFPUnitName   !                              then  = 'Centimeters'
  integer(4)::iPixelsPerUnit!in the same unit as L,R,T,B & D
  real(8)   ::UlcPixelXyz(3)!exact 3D coordinates of the center of the UL pixel
 end type VisionGeometryRec
  type(VisionGeometryRec)::V,Vreset
! Note#1: The individual values in the record are not accessed or used (by me);
!            the V. record provides a convenient central place to define them.
!         The variable names are locally defined & the vector(_,jVG) values
!           are unpacked within the subroutine(s) that operate on those values.
!////////

!--- Other variables:
! real(8)  ::Cu( 14),Du( 12),Fu( 4,4),Fou( 4,4) !Compacts source code

  character::cVuModeName(0:2)*17=(/ 'e=0: Orthographic'  &        !Centered *17
                                   ,'e=1:  Perspective'   &
                                   ,'e=2:    Stereo 3D'      /)

  character::cEyeName(-1:1)  *21=(/ '  Left  Eye`s  View  '&             !C *21
                                   ,'Left:Red | Right:Cyan'&
                                   ,'  Right Eye`s  View  ' /)

  character::cSplitName(-1:1)*32=(/ 'E=-1: Right|Left-> Crossed-Eye  '&  !C *32
                                   ,'        E= 0: Full-Screen       '&
                                   ,'E=+1: Left|Right-> CellPhone HMD' /)

  character::cFrustumUnits*12 ='     Inches'   !11 char. right justified
                             !='Centimeters'
                             !='   Whatever'
  character::ClipLabel(1:16)*7 =  &
                 (/ '1Near  ','2Far   ','3Left  ','4Right ' &
                   ,'5Upper ','6Lower ','7undef ','8undef ' &
                   ,'1Near  ','2Far   ','3LfarL ','4RnearL' &
                   ,'5RfarR ','6LnearR','7Upper ','8Lower '  /)
  character::ClipSymbolicLabel(16)*64 = (/ &
 !Orthographic
 '-1.                  0.                  0.                 -N  '& !1 Near
,'+1.                  0.                  0.                 +F  '& !2 Far
,' 0.                 -1.                  0.                 -L  '& !3 Left
,' 0.                 +1.                  0.                 +R  '& !4 Right
,' 0.                  0.                 +1.                 -T  '& !5 Upper
,' 0.                  0.                 -1.                 +B  '& !6 Lower
,' 0.                  0.                  0.                  0. '& !7 undef
,' 0.                  0.                  0.                  0. '& !8 undef
 !Projective
,'-1.                  0.                  0.                 -N  '& !1 Near
,'+1.                  0.                  0.                 +F  '& !2 Far
,'-L-E                +D                   0.                 -D*L'& !3 LfarL
,'-L+E                +D                   0.                 -D*L'& !4 RnearL
,'+R-E                -D                   0.                 +D*R'& !5 RfarR
,'+R+E                -D                   0.                 +D*R'& !6 LnearR
,'-T                   0.                 +D                  -D*T'& !7 Upper
,'+B                   0.                 -D                  +D*B'/)!8 Lower
!contains
End Module ViewDef
!---------------------------------------------------------------------------7 9

Module ModelDef
!use ModelDef      !--On screen control of PoI DoF's:            JMS 2020.06.30
!--------------------------------------
!--Motion 7DoF control record:
 type ::  Motion7Rec ;Sequence
  real(8)   ::DoF(7)        !(/ X,Y,Z,Roll,Pitch,Yaw,Mag /)
  real(8)   ::H(4,4)        !Homogeneous motion transform of Dof(1:7)
  real(8)   ::DoFreset(7)   !Nominal Value of each DoF
  real(8)   ::Sens(7)       !Screen sensitivity of each DoF
!                           =(/.05d0,.05d0,.05d0,1.0d0,1.0d0,1.0d0,.01d0/)
  integer(4)::n             !Record index- M7(n)
  character::ID*20         !Name
  !--Control of the above: e.g. via keyboard & Mouse:
  integer(4)::iType         !=0:control as- Point-of-Interest
                           !=1:          - Flight Simulation object
  integer(4)::Locked(0:7)   !=0: DoF()- can be changed
                           !=1:      - value is locked
  integer(4)::ie            !=1: Control- interior
                           !=2:        - exterior
  integer(4)::ioe(0:2)      !(0)- =1: Primary control- vertical- X,Z,Pitch,Mag
                           !     =2:                - lateral - Y,Roll,Yaw
                           !(1)    :Controlled DoF- vertical
                           !(2)    :              - lateral
  integer(4)::DoFsInUse(0:7)!=0 not under control
                           !=1 primary   #1 -onscreen
                           !=2 secondary #2 -
  integer(4)::M7Init        !=0: Initialized: no
                           !=1:            : yes
 end type Motion7Rec
  type(Motion7Rec)::M7(0:10),M7u,M7zero
!         Nominally M7(0) is the Point-of-Interest controller,
!           & the rest are per user discretion.
  common /Motion7Com/ M7com

  real(8)   ::DoFL(7)        !(/ X,Y,Z,Roll,Pitch,Yaw,Mag /)
  real(8)   ::H(4,4)        !Homogeneous motion transform of Dof(1:7)
  real(8)   ::DoFreset(7)   !Nominal Value of each DoF
  real(8)   ::Sens(7)       !Screen sensitivity of each DoF
  integer(4)::nM7L          !Record index- M7(n)
  character::ID*20         !Name
  integer(4)::iType         !=0:control as- Point-of-Interest
                           !=1:          - Flight Simulation object
  integer(4)::Locked(0:7)   !=0: DoF()- can be changed
                           !=1:      - value is locked
  integer(4)::iec           !=1: Control- interior
                           !=2:        - exterior
  integer(4)::ioe(0:2)      !(0)- =1: Primary control- vertical- X,Z,Pitch,Mag
                           !     =2:                - lateral - Y,Roll,Yaw
                           !(1)    :Controlled DoF- vertical
                           !(2)    :              - lateral
  integer(4)::DoFsInUse(0:7)!=0 not under control
                           !=1 primary   #1 -onscreen
                           !=2 secondary #2 -
  integer(4)::M7Init        !=0: Initialized: no
                           !=1:            : yes
!use ModelDef, only: &
!       DoFL,H,DoFreset,Sens,nM7L,ID,iType,Locked,ie,ioe,DoFsInUse,Init

  real(8)   ::X,Y,Z,Roll,Pitch,Yaw,Mag
  real(8)   ::hPoIRotate(4,4)!             - rotation only transform
  integer(4)::Flags(5,2)=0  !(1m|2a|3m|4a|5k , 1:I|2:e) 7DoF control array

 !--Flight Sim 7DoF body control:
! "Seven DoF Point-of-View Control:" &  !  1 Gray
  character*32::c7DoFID(15) = (/ &
  "Seven DoF Control:              " &  !  1 Gray
 ,"                 . Lock    > ^  " &  !  2 DkGray
 ,"                   1 X      #  |" &  !  3 Gray
 ,"                   2 Y    #    -" &  !  4 Gray
 ,"                   3 Z      #  |" &  !  5 Gray
 ,"                   4 Roll #    -" &  !  6 Gray
 ,"                   5 Pitch  #  |" &  !  7 Gray
 ,"                   6 Yaw  #    -" &  !  8 Gray
 ,"                   7 Mag    #  |" &  !  9 Gray
!  ^1             18^ ^20   28^ ^30
 ,"   Arrowkeys & LMB+motion: ^ ^  " &  ! 10 DkGray
 ,"enable NumLock INTERIOR control " &  ! 11 White
 ,"       7:Mag  8:reset 9:INT|EXT " &  ! 12 DkGray
 ,"       4:Roll 5:Pitch 6:Yaw     " &  ! 13 DkGray
 ,"   ^   1:X    2:Y     3:Z       " &  ! 14 DkGray
 ," < v > 0:zero#1       .:Lock#1  "  /)! 15 DkGray
  integer(4)::iColors(15) & !color (state+3)
                        =(/ 1, 3, 2, 2, 2, 2, 2, 2, 2, 3,1, 3, 3, 3, 3/)
!                       =(/11,12,11,11,11,11,11,11,11,12,1,12,12,12,12/)
                       !            X  Y  Z  r p y  M   (DoF+3)

!--7DoF variable identifiers:
  character*6::cDoFID(0:7) = (/ "undef0" &
                               ,"    X1" &
                               ,"    Y2" &
                               ,"    Z3" &
                               ," Roll4" &
                               ,"Pitch5" &
                               ,"  Yaw6" &
                               ,"  Mag7"  /)

!--Model nutation... enables monocular depth perception:
  integer(4)::Nnutate      !=0:off, =1:on
  real(8)   ::NutateAng    !Angle
  real(8)   ::Nutate7(7)   !(X,Y,Z,Roll,Pitch,Yaw,Mag)
  real(8)   ::Nutateh(4,4) !H matrix

 !--VuDef has same name variables:
  integer(4)::nRowOffset = 33   !Screen text offset - vertical      ...Seeh44d()
  integer(4)::nRowIn
  integer(4)::nColOffset =  1   !                   - lateral
  integer(4)::nColIn
!Contains
End Module ModelDef
!---------------------------------------------------------------------------7 9
Module SimDef
!use SimDef            !Simulation control,F9-F12
 !--F9-F12 control,timers:
  integer(4)::SimMode   !=-1:ReStartup  'Delete' key          Sets Init=0
  integer(4)::SimModeNew!= 0:Startup nAppInUseChanged>0
                       != 1:Reset   F 9 <-Function keys  RunTimer=        0.00
                       != 2:Hold    F10
                       != 3:Run     F11                  RunTimer=RunTimer+.01
                       != 4:Stop    F12
                       != 5:Quit    'Q'or'q'... pressed twice
  real(8)   ::dT=.01d0  !Simulation time increment
  real(8)   ::RunTimer  !A clock that increments during "Run" +dT for each iter.
  real(8)   ::UserTimer !
  integer(4)::Fnew      != Function keypress
 !--Iteration counters:
  integer(4)::IterTotal !Iteration counter- total since launching 3DEnv.exe
                       !                  e.g.: used to close opening messages.
  integer(4)::IterRun;  !                - total in the current 'Run' (F11->Run)
 !--Millisec counter:
  real(8)   ::RunSecs   !Elapsed seconds since program launch, msec resolution.
                       !
!Contains
End Module SimDef
!---------------------------------------------------------------------------7 9
Module HelpDef
!use HelpDef            !Help (a text block)                     JMS 2024.03.18
 integer(4)::HhHelpView      !Use: Hh: -displays the Help
 integer(4):: nHelpLines=46
 character:: BufferHhHelpView(46)*73=(/                                      &
 '      The `H`/`h` (=Help) key toggles this screen information.           ' &
,'                                                                         ' &
,'These algorithms support split screen left|right & right|left, and also  ' &
,'  a full screen display mode, with orthographic, perspective, & stereo   ' &
,'  viewing options in each display mode. [The gem of code underlying this ' &
,'  functionality is subroutine ViewGeom in file S6View8.f95.] Apps are    ' &
,'  called from within this live double-buffered environment.              ' &
,'                                                                         ' &
,'Pressing `P` hardcopies the homogeneous projection(s) to Sn3D-Out.txt,   ' &
,'  while  `p` prints them on the DOS screen, which can be viewed          ' &
,'  by toggling the `Escape` key. Writes to unit#`Up` are reported during  ' &
,'  that iteration, simplifying at-will focused quantitative snapshots of  ' &
,'  your algorithms in action.                                             ' &
,'                                                                         ' &
,'Nutation is toggled by `Nn`, yielding monocularly-perceivable depth.     ' &
,'                                                                         ' &
,'In simulations, rigid bodies often have 6 Degree-of-Freedom ("=6DoF")    ' &
,'  motion (X,Y,Z,Roll,Pitch, & Yaw); herein Standard Flight Simulation    ' &
,'  Coordinates are used (+X:forward, +Y:right, +Z:down, etc.). In viewing ' &
,'  your particular point-of-interest ("PoI"), magnification is added      ' &
,'  as the 7th DoF. Exterior control of PoI is also implemented (`9`).     ' &
,'                                                                         ' &
,'The numeric keypad and mouse (LMB-down) provide interactive control of   ' &
,'  the 6DoF and 7Dof states. E.g.: Left-click a DoF name to select it.    ' &
,'Keyboard keys:           Apps Access:            Simulation Ctls:        ' &
,'  Cc:Screen Color           F1:Application Stub    F 9:Reset             ' &
,'  E : display mode          F2:Dodecahedron Vis.   F10:Hold              ' &
,'    =0:  full    screen     F3:                    F11:Run               ' &
,'    =1:Left|right split     F4:                    F12:Stop              ' &
,'    =2:right|left split     F5:                    ...runs RunTimer      ' &
,'   e: projection            F6:                     & sets SimMode       ' &
,'    =0:orthographic         F7:                    for your convenience. ' &
,'    =1:perspective          F8:PixelDraw                                 ' &
,'    -2:stereovision               Turn NumLock on!                       ' &
,'  Hh:help screen          Numeric keypad 6DoF & 7DoF control:            ' &
,'  M :8 free Mchan[0.,1.]`s  1:X                 Left Mouse Button=LMB    ' &
,'   m:7Dof/6Dof toggle       2:Y                 and arrow keys           ' &
,'  Nn:2 model Nutation modes 3:Z                 can also be used.        ' &
,'  P :Print to-.txt file     4:Roll                                       ' &
,'   p:        -DOS screen    5:Pitch             See onscreen summary.    ' &
,'  Qq:Quit                   6:Yaw                                        ' &
,'  Tt:7 Teapot views         7:Mag                The teapot is an        ' &
,'  Vv:2 Viewing info modes   8:Reset 1:7         example 7DoF object.     ' &
,'                            9:Interior/Exterior PoI control              ' &
,'                            0:Resets most recently selected DoF #1       ' &
,'Sn3D.exe  V1.0  2025.05.24                             In S1ModDef @L665+' /)
!Contains
End Module HelpDef
!---------------------------------------------------------------------------7 9
Module AppsDef
!use AppsDef            !User Apps F1-F8                         JMS 2020.06.19
!*** Application Selection:
  integer(4)::AppNumber      !# of app. you are viewing.
  integer(4)::AppNumberNew   !Use: F_ =[1,...,8] ... the Function keys
  character::AppName*80
  integer(4)::AppInit(8) = 0 !      - initialization flag= 0:no
                            !                           = 1:done
  integer(4)::IterApp(  0:8) !Present-use iterations of app (_)
  character::AppBanner(0:8)*58= char(0) !App- banner    (left side,2nd line)
                                   !            defined in each app
  character::AppInFIle(0:8)*35= char(0) !   - Input data

!Contains
End Module AppsDef
!---------------------------------------------------------------------------7 9
Module F3dvDef
!use F3dvDef            !File .3dv data                          JMS 2020.06.19
!*** .3dv 3D Data Access (App F5 - not included in v:c0,5):------------
  integer(4)::Init3dv
  character::File3dv*35   !3dv- filename. Default:"DrawingFS.3dv"
  integer(4)::U3dv         !   - file unit number      (was:fp3dv)
  integer(4)            ::nPoints       !Points  - number
  real(8)   ,allocatable :: Points(:,:) !        - vectors (3,nPoints)
  integer(4)            ::nConns        !connects- number
  integer(4),allocatable::iConns( :,:)  !        - table   (2,nConns)

!Contains
End Module F3dvDef
!---------------------------------------------------------------------------7 9
Module BreakPtDef
!use BreakPtDef         !BreakPoint and scrolling tracker        JMS 2020.06.29
!*** Break point control: "BrkVal=Brk(BrkRefNum,BrkN,BrkM)":-----------
  integer(4)::BrkOn  !=0:off,=1:on. When on: +- keys move BrkLim
  integer(4)::BrkLim !Progress- counting- Reference
  integer(4)::BrkCur !                  - incremental count1<=P<=Pref
                    !                    return when P=Pref
  integer(4)::BrkVal
  integer(4)::BrkLineNum
  integer(4)::BrkN
  integer(4)::BrkM
  integer(4)::BrkDone              !        - completion flag when >0
  character::BrkLab*80 ![80]      !        - label- incremental
  character::BrkLabelOut*80 ![80] !               - Output when P=PRef

!Contains
End Module BreakPtDef
!---------------------------------------------------------------------------7 9
!This module must list last, otherwise the compiler 'use' sequence is violated.
!  I.e.: Don't use modules before they're defined.
Module UseAllSnDef                                              !JMS 2024.05.02
!use UseAllSnDef        !Contents                                JMS 2020.06.19
!use OpenGLRec          !The OpenGL GL,GLU,GLUT interface        JMS 2020.06.19
 use TaskDef            !Project/Context                         JMS 2020.06.19
 use ioDef              !Files,Units,TimeStamp,Selfies,Flags     JMS 2020.06.19
 use ScreenDef          !screen & colors                         JMS 2020.06.19
 use KeyboardDef        !Keyboard                                JMS 2020.06.19
 use MouseDef           !Mouse                                   JMS 2020.06.19
 use ViewDef            !View bounds->[0.,+1.]->[extent]Destination  2020.06.19
 use ModelDef           !Modelview Matrix Generation             JMS 2020.06.19
 use SimDef             !Simulation F9-F12                       JMS 2020.06.19
 use HelpDef            !Help text block                         JMS 2020.06.19
 use AppsDef            !User Apps F1-F8                         JMS 2020.06.19
 use F3dvDef            !File .3dv data                          JMS 2020.06.19
 use BreakPtDef         !BreakPoint Tracker                      JMS 2020.06.19

 !Contains
End Module UseAllSnDef
!---------------------------------------------------------------------------7 9

!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!~~~~~~~~~~~~~ Template-begin:                          2020.06.19.1450cdt JMS-
!use _Def      ,only: & !Contents                                    2020.06.19
!
!Module __Def
!use _Def               !Contents                                    2020.06.19
!    ,~
!Contains
!End Module __Def
!---------------------------------------------------------------------------7 9
!~~~~~~~~~~~~~ Template- end.
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

