c
c     Copyright (c) 1999,2000, Compaq Computer Corporation
c
c     See the file "license.terms" for information on usage and redistribution
c     of this file, and for a DISCLAIMER OF ALL WARRANTIES.
c
      subroutine surf_copy_transform_3d (source, destination)
      implicit none
c
c     Makes a duplicate copy of a transformation matrix.
c
      real source(4,4), destination(4,4)
c      
      integer row, col
c
      do row=1,4
         do col=1,4
            destination(row,col) = source(row,col)
         end do
      end do
c
      return
      end
c
      subroutine surf_translate_transform_3d (ray, xform)
      implicit none
c
c     Translation transformation. The argument ray is the translation vector.
c      
      real ray(4)
      real xform(4,4)
c      
      real current(4,4)
      real right(4,4)
c
      data right / 1.0,   0.0,   0.0,   0.0,
     +             0.0,   1.0,   0.0,   0.0,
     +             0.0,   0.0,   1.0,   0.0,
     +             0.0,   0.0,   0.0,   1.0/
      save right, current
c      
      call surf_copy_transform_3d (xform, current)
c      
      right (4,1) = ray(1)
      right (4,2) = ray(2)
      right (4,3) = ray(3)
c      
      call surf_matrix_mult (4, current, right, xform)
c
      return
      end
c
      subroutine surf_right_left(xform)
      implicit none
c
c     right_left(xform) switches from a right-handed coordinate system
c     to a left handed one.
c      
      real xform(4,4)
c
      real current(4,4)
      real right(4,4)
c
      data right / 0.0,  0.0,   0.0,   0.0,
     +             0.0,  1.0,   0.0,   0.0,
     +             0.0,  0.0,   1.0,   0.0,
     +             0.0,  0.0,   0.0,   1.0/
      save right, current
c
      call surf_copy_transform_3d (xform, current)
      right (1,1) = -1.0
      call surf_matrix_mult (4, current, right, xform)
c      
      return
      end
c
      subroutine surf_rotate_x_transform_3d (cosine, sine, xform)
      implicit none
c
c     Rotate around x axis by an angle specified by the cosine and sine.
c
      real cosine, sine
      real xform(4,4)
c
      real current(4,4)
      real right(4,4)
c
      data right / 1.0,  0.0,   0.0,   0.0,
     +             0.0,  0.0,   0.0,   0.0,
     +             0.0,  0.0,   0.0,   0.0,
     +             0.0,  0.0,   0.0,   1.0/
      save right, current
c      
      call surf_copy_transform_3d (xform, current)
      right (2,2) = cosine
      right (2,3) = sine
      right (3,2) = (- sine)
      right (3,3) = cosine
      call surf_matrix_mult (4, current, right, xform)
c
      return
      end      
c      
      subroutine surf_rotate_y_transform_3d (cosine, sine, xform)
      implicit none
c
c     Rotate around y axis by an angle specified by the cosine and sine.
c      
      real cosine, sine
      real xform(4,4)

      real current(4,4)
      real right(4,4)
      data right /0.0, 0.0, 0.0, 0.0 ,
     +            0.0, 1.0, 0.0, 0.0 ,
     +            0.0, 0.0, 0.0, 0.0 ,
     +            0.0, 0.0, 0.0, 1.0/
      save current, right
c      
      call surf_copy_transform_3d (xform, current)
      right (1,1) = cosine
      right (1,3) = sine
      right (3,1) = (- sine)
      right (3,3) = cosine
      call surf_matrix_mult (4, current, right, xform)
c
      return
      end
c
      subroutine surf_rotate_z_transform_3d (cosine, sine, xform)
      implicit none
c
c     Rotate around z axis by an angle specified by the cosine and sine.
c      
      real cosine, sine
      real xform(4,4)
c      
      real current(4,4)
      real right(4,4)
      data right/0.0, 0.0, 0.0, 0.0,
     +           0.0, 0.0, 0.0, 0.0,
     +           0.0, 0.0, 1.0, 0.0,
     +           0.0, 0.0, 0.0, 1.0/
      save current, right
c      
      call surf_copy_transform_3d (xform, current)
      right (1,1) = cosine
      right (1,2) = sine
      right (2,1) = (- sine)
      right (2,2) = cosine
      call surf_matrix_mult (4, current, right, xform)
c
      return
      end
c      
      subroutine surf_shear_z_transform_3d (a, b, xform)
      implicit none
c
c     surf_shear_z_transform()
c      
      real a, b
      real xform(4,4)
c      
      real current(4,4), right(4,4)
      data right/1.0, 0.0, 0.0, 0.0,
     +           0.0, 1.0, 0.0, 0.0,
     +           0.0, 0.0, 1.0, 0.0,
     +           0.0, 0.0, 0.0, 1.0/
      save current, right
c      
      call surf_copy_transform_3d (xform, current)
      right (3,1) = a
      right (3,2) = b
      call surf_matrix_mult (4, current, right, xform)
c
      return
      end
c
      subroutine surf_scale_transform_3d (ray, xform)
      implicit none
c
      real ray(4)
      real xform(4,4)
c
      real current(4,4), right(4,4)
      data right/0.0, 0.0, 0.0, 0.0,
     +           0.0, 0.0, 0.0, 0.0,
     +           0.0, 0.0, 0.0, 0.0,
     +           0.0, 0.0, 0.0, 1.0 /
      save current, right
c      
      call surf_copy_transform_3d (xform, current)
      right (1,1) = ray(1)
      right (2,2) = ray(2)
      right (3,3) = ray(3)
      call surf_matrix_mult (4, current, right, xform)
c      
      return
      end
c
      subroutine surf_transform_point_3d (input, xform, output)
      implicit none
c
c     surf_transform_point_3d() transforms the coordinates of a 3d point by the 
c     specified transformation.
c
      real input(4), output(4)
      real xform(4,4)
c      
      input(4) = 1.0     ! set global scale factor
      call surf_vector_matrix_mult (4, input, xform, output)
c      
      if (output(4) .ne. 0) then
          output(1) = output(1)/output(4)
          output(2) = output(2)/output(4)
          output(3) = output(3)/output(4)
          output(4) = 1.0
      endif
c      
      return
      end
c
      subroutine surf_transform_ray_3d (input, xform, output)
      implicit none
c
c     surf_transform_ray_3d() transforms the coordinates of a 3d point by the 
c     specified transformation.
c
      real input(4), output(4)
      real xform(4,4)
c      
      input(4) = 0.0      ! set global scale factor
      call surf_vector_matrix_mult(4, input, xform, output)
      if (output(4) .ne. 0)  then
          output(1) = output(1)/output(4)
          output(2) = output(2)/output(4)
          output(3) = output(3)/output(4)
          output(4) = 1.0
      endif
c
      return
      end
