home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / library / os2 / rsg_ray / rt.txt < prev    next >
Encoding:
Text File  |  1993-11-10  |  29.8 KB  |  759 lines

  1. CSG Ray Tracer
  2.  
  3. (C) 11/11/93 A.Key
  4.  
  5.  
  6. Introduction
  7. ------------
  8.  
  9. This ray-tracer based on information given in "Computer Graphics, Principles
  10. and Practice", by Foley, vanDam, Feiner and Hughes, and Byte magazine.
  11.  
  12. The input file is an ASCII text file that defines surface colours and
  13. shapes etc.. Such text files may include other text files. Also, bitmaps
  14. may be supplied for 2D texture field maps, and .tex files can be supplied for
  15. 3D texture field maps. The recommended extension for ray-tracer files
  16. is .rt, and the Andys Editor language definition should have a reserved
  17. comment start of ";..." and end of "", since ";"'s are used to introduce
  18. comments.
  19.  
  20.  
  21. Shading Model
  22. -------------
  23.  
  24. The shading model is as given on p734.
  25.  
  26. Each surface has ambient, diffuse, specular and transmissive coefficients,
  27. called ka,kd,ks and kt.
  28.  
  29. It also has a diffuse colour, od and a specular colour os. The specular colour
  30. is used to compute highlights with, and is usually white-ish for plastic-like
  31. surfaces.
  32.  
  33.   I = Ia * ka * od                    Ambient
  34.     + fatt * Ip * kd * od * cos_nl            Diffuse (per light)
  35.     + fatt * Ip * ks * os * pow(cos_rv, phong_power)    Specular (per light)
  36.  
  37. If no surface is hit, then I = Ib, where Ib is a background colour.
  38.  
  39.  
  40. Objects traceable
  41. -----------------
  42.  
  43. The objects that may be traced are half-planes (planes for short), spheres and
  44. arbitrary quadratics. The solid parts are the regions below :-
  45.  
  46.     Plane:        ax+by+cz+d<=0
  47.  
  48.     Biplane:    ax+by+cz+d2<=0 and not ax+by+cz+d1<=0
  49.  
  50.                  2      2      2  2
  51.     Sphere:        (x-a) +(y-b) +(z-c) -d <=0
  52.  
  53.               2   2   2
  54.     Quadratic:    ax +by +cz +dxy+eyz+fzx+gx+hy+iz+j<=0
  55.  
  56. Boolean combinations of the above are allowable too. Clearly planes and spheres
  57. are just special cases of the general quadratic case, when certain coefficents
  58. are 0. However, such primitives are implemented in the indicated faster ways.
  59.  
  60.  
  61. Input file format/language
  62. --------------------------
  63.  
  64. The following types are understood by the tracer :-
  65.  
  66.     value        A numeric value
  67.     xyz        A 3 element vector, used for positions and directions
  68.     rgb        A 3 element colour intensity vector
  69.     col        A colour (rgb, but can vary dependant on position)
  70.     surf        A surface structure
  71.     shape        Any of the traceable shapes
  72.  
  73. The following functions (rvalues) are provided. Variables are of the type
  74. value unless of the form a_xxx, in which case they are of type xxx :-
  75.  
  76.     radians = rad(degrees)
  77.         Converts an angle in degrees to the value in radians
  78.  
  79.     a_xyz = xyz(x,y,z)
  80.         Returns a vector with the 3 specified values
  81.  
  82.     a_xyz = trans_x(a_xyz,dx)
  83.         Returned vector has x component dx bigger.
  84.         Similar functions trans_y and trans_z also exist
  85.  
  86.     a_xyz = trans(a_xyz,a_xyz)
  87.         Returns sum of 2 vectors.
  88.  
  89.     a_xyz = scale_x(a_xyz,factor)
  90.         Returns a vector, scaled by factor in x direction.
  91.         Similar functions scale_y and scale_z also exist
  92.  
  93.     a_xyz = scale(a_xyz,a_xyz_factor)
  94.         Returns a vector, scaled by factor
  95.  
  96.     a_shape = rot_x(a_xyz,angle)
  97.         Returns a vector rotated by angle around x axis
  98.         Angle is specified in radians
  99.         Similar functions rot_y and rot_z exist
  100.  
  101.     a_rgb = rgb(red,green,blue)
  102.         Makes an RGB colour value out of 3 components
  103.         eg: set_col shiny_red surf(0.2,0.6,0.2,0.0,
  104.                        rgb(1.0,0.0,0.0),
  105.                        rgb(1.0,1.0,1.0),
  106.                        200,1)
  107.  
  108. Note that reserved words trans_x, trans, scale_x, scale, rot_x and related y
  109. and z forms here operate on vectors and return vectors. Later, we will see
  110. that the same words also operate on shapes to give new shapes. Which is mean't
  111. is easily determined from the context.
  112.  
  113. A colour is something that is defined to be a given RGB value for a given
  114. point in space. Since colours can be defined in terms of colours, there is
  115. conceptually a colour 'tree'. When the root colour is evaluated, it is passed
  116. 3 parameters (known as p0,p1 and p2) and these are the x,y and z of the
  117. intersection point on the surface of the shape.
  118.  
  119.     a_col = col(a_rgb)
  120.         Makes a colour that is the same regardless of position.
  121.  
  122.     a_col = col_field2d(bx,by,"fn.bmp")
  123.         Makes a colour that takes the passed in p0 and p1 (ignoring
  124.         p2) and uses (p0+bx,p1+by) to index a bitmap specified.
  125.         On its own, such a colour can only map a bitmap across the
  126.         x-y plane. With this primitive (and col_remap) bitmaps may
  127.         be mapped over the surfaces of objects.
  128.         eg: set_col floor_col col_field2d(0,0,"tiles.bmp")
  129.  
  130.     a_col = col_field3d(bx,by,bz,"fn.tex")
  131.         Makes a colour that takes the passed in p0,p1, and p2 and
  132.         uses (p0+bx,p1+by,p2+bz) to index the texture-map file.
  133.         On its own, such a colour can only map a texture-map that
  134.         is parallel to the x,y and z axes.
  135.  
  136.     a_col = col_interp0(a_col_arg)
  137.         Perform linear interpolation of p0 argument.
  138.         col_interp1 and col_interp2 also exist.
  139.         eg: if p0 was 2.5, then evaluates a_col_arg with p0 at 2.0
  140.         and also at 3.0 and finds the average colour.
  141.         eg: set_col floor_col col_interp0(
  142.                     col_interp1(
  143.                       col_field2d(0,0,"tiles.bmp")))
  144.  
  145.     a_col = col_remap(a_xyz_base,
  146.               a_xyz_v0,
  147.               a_xyz_v1,
  148.               a_xyz_v2,a_col_arg)
  149.         The (p0,p1,p2) are taken to be cartesian xyz coordinates
  150.         when this colour is evaluted. New values p0',p1' and p2' are
  151.         computed where a_xyz_base + p0' * a_xyz_v0 + p1' * a_xyz_v1 +
  152.         p2' + a_xyz_v2 = (p0,p1,p2).
  153.         ie: (p0,p1,p2) is transformed to a new coordinate space, based
  154.         at a_xyz_base in the old coordinate space, with axes given by
  155.         vectors a_xyz_v0, a_xyz_v1 and a_xyz_v2. The new
  156.         coordinate is passed to a_col_arg when it is evaluated.
  157.         When a colour is rotated/translated (when the shape it is used
  158.         by is rotated/translated, this colour is (ie: these vectors
  159.         are) is adjusted to move with the shape.
  160.         Similarly, when a shape is scaled, its colour is scaled too.
  161.         This will cause the base and basis vectors to be scaled too.
  162.  
  163.     a_col = col_cyl(lond,rd,hd,a_col_arg)
  164.         The (p0,p1,p2) are taken to be cartesian xyz coordinates.
  165.         The x-y plane can be considered the equator.
  166.         The z axis can be considered the polar axis.
  167.         A new p0 is computed as the longitude / lond.
  168.         A new p1 is computed as the radius / rd.
  169.         A new p2 is computed as the height (= original p2) / hd.
  170.         The values are passed down to a_col_arg.
  171.         This is used to perform cylindrical polar texture maps.
  172.         eg: set_col x col_remap(xyz(1,2,3),xyz(1,0,0),xyz(0,1,0),
  173.                 col_cyl(rad(1),1,1,
  174.                   col_mat3d(1,0,0,
  175.                             0,0,1,
  176.                             0,1,0,
  177.                     col_field2d(0,0,"360x100.bmp"))))
  178.  
  179.     a_col = col_sph(lond,latd,rd,a_col_arg)
  180.         The (p0,p1,p2) are taken to be cartesian xyz coordinates.
  181.         The x-y plane can be considered the equator.
  182.         The z axis can be considered the polar axis.
  183.         A new p0 is computed as the longitude / lond.
  184.         A new p1 is computed as the latitude / latd.
  185.         A new p2 is computed as the radius / rd.
  186.         The values are passed down to a_col_arg.
  187.         This is used to perform spherical polar texture maps.
  188.         eg: set_col earth_col col_remap(xyz(0,0,0),xyz(1,0,0),xyz(0,1,0),
  189.                     col_sph(rad(1),rad(1),1,
  190.                       col_field2d(0,90,"360x180.bmp")))
  191.         
  192.     a_col = col_nomove(a_col_arg)
  193.         When objects of a given colour are translated, rotated or
  194.         scaled, as well as the objects shape being moved, the objects
  195.         colour is moved too. Unless this primitive is used.
  196.         eg: set_col col_dep_on_scene_not_object col_nomove(a_col_arg)
  197.  
  198.     a_col = col_mat2d(a00,a01,
  199.               a10,a11,a_col_arg)
  200.         2x2 matrix modification of (p0,p1,p2) and chain on
  201.         q0 = a00 * p0 + a01 * p1
  202.         q1 = a10 * p0 + a11 * p1
  203.         Evaluate a_col_arg with q0,q1,p2
  204.         This allows you arbitrarily remap p0,p1,p2 in terms of
  205.         one another. It is useful for mapping textures at obscure
  206.         angles around shapes, and changing the ordering of p0 and p1
  207.  
  208.     a_col = col_mat3d(a00,a01,a02,
  209.               a10,a11,a12,
  210.               a20,a21,a22,a_col_arg)
  211.         3x3 matrix modification of (p0,p1,p2) and chain on
  212.         q0 = a00 * p0 + a01 * p1 + a02 * p2
  213.         q1 = a10 * p0 + a11 * p1 + a12 * p2
  214.         q2 = a20 * p0 + a21 * p1 + a22 * p2
  215.         Evaluate a_col_arg with q0,q1,q2
  216.         Similar uses as above.
  217.         Particularly useful with col_cyl.
  218.         eg: set_col a_col col_remap(xyz(0,0,0),xyz(1,0,0),xyz(0,1,0),
  219.                             col_cyl(rad(1),1,1,
  220.                                       ; here p0=longitude,p1=radius,p2=height
  221.                               col_mat3d(1,0,0,
  222.                                         0,0,1,
  223.                                         0,1,0,
  224.                                 ; here p0=longitude,p1=height,p2=radius
  225.                                 col_field2d(0,90,"bitmap.bmp"))))
  226.  
  227. The structures above give the ability to map bitmaps anywhere in space - for
  228. example, on the sides of objects. Also the ability to do 3d texture mapping.
  229. Also interpolation between pixels in texture maps is optional in any or all
  230. of the directions in the texture map. Cylindrical polar and spherical polar
  231. mapping may be performed. Colour fields may move with the object when it is
  232. moved, or stay fixed against a given reference point (ie: the backdrop).
  233.  
  234. It is admitted that this is complicated, and a few worked examples are
  235. given later.
  236.  
  237. Every shape has its surfaces defined as the combination of various
  238. coefficients and ambient and diffuse colours. Phong power and refractive
  239. index also contributes to the overall effect.
  240.  
  241.     a_surf = surf(ka,kd,ks,kt,a_col_od,a_col_os,
  242.               phong_power,refractive_index)
  243.         Makes a surface colour structure
  244.         Supply ambient, diffuse, specular and transmissive coeffs.
  245.         Supply diffuse and specular colours
  246.         Supply phong power and refractive index
  247.  
  248.     a_shape = plane(a,b,c,d,a_surf)
  249.         Returns a half-plane solid for ax+by+cz+d<=0
  250.         This primitive is traced quicker than a general quadratic
  251.  
  252.     a_shape = x_lt(x,a_surf)
  253.         Returns a shape solid for x <= some x value
  254.         Similar functions x_gt, y_lt, y_gt, z_lt and z_gt also exist
  255.  
  256.     a_shape = biplane(a,b,c,d1,d2,a_surf)
  257.         Returns a half-plane solid for ax+by+cz+d1>0 and ax+by+cz+d2<=0
  258.         This primitive is traced quicker than a general quadratic,
  259.         and is also traced quicker than the intersection of 2 planes.
  260.  
  261.     a_shape = x_in(x1,x2,a_surf)
  262.         Returns a shape solid for x in x1 to x2.
  263.         Similar functions y_in and z_in also exist.
  264.  
  265.     a_shape = sphere(r,a_surf)
  266.         Returns a solid sphere, radius r, at the origin
  267.         This primitive is traced quicker than a general quadratic
  268.  
  269.     a_shape = ellipsoid(rx,ry,rz,a_surf)
  270.         Returns an ellipsoid at the origin with given radii
  271.  
  272.     a_shape = x_ell_cyl(ry,rz,a_surf)
  273.         Returns a elliptical cylinder along the x axis with given radii
  274.         Similar functions y_ell_cyl, z_ell_cyl also exist
  275.  
  276.     a_shape = x_cyl(r,a_surf)
  277.         Returns a cylinder along the x axis with given radius
  278.         Similar functions y_cyl, z_cyl also exist
  279.  
  280.     a_shape = x_ell_cone(ky,kz,a_surf)
  281.         Returns a elliptical cone along the x axis with given
  282.         gradients to the y and z axis
  283.         Similar functions y_ell_cone, z_ell_cone also exist
  284.  
  285.     a_shape = x_cone(k,a_surf)
  286.         Returns a cone along the x axis with given gradient
  287.         Similar functions y_cone, z_cone also exist
  288.  
  289.     a_shape = quad(a,b,c,d,e,f,g,h,i,j,a_surf)
  290.         Returns a general quadratic as described above
  291.         If a to f are 0, a half-plane results
  292.         If d to i are 0, and a=b=c sphere around the origin results
  293.         In these two cases, the functions above are traced faster
  294.  
  295.     a_shape = trans_x(a_shape,x)
  296.         Returns a copy of the shape, translated by x in the x direction
  297.         Similar functions trans_y and trans_z also exist
  298.  
  299.     a_shape = trans(a_shape,a_xyz)
  300.         Returns a copy of the shape, translated by a given vector
  301.         Note:    trans(a_shape,xyz(x,y,z)) =
  302.             trans_x(trans_y(trans_z(a_shape,z),y),x)
  303.  
  304.     a_shape = scale_x(a_shape,factor)
  305.         Returns a copy of the shape, scaled by factor in x direction.
  306.         (A sphere scaled in this way becomes a general quadratic).
  307.         Similar functions scale_y and scale_z also exist
  308.  
  309.     a_shape = scale(a_shape,a_xyz_factor)
  310.         Returns a copy of the shape, scaled in x, y and z by amounts.
  311.         (A sphere scaled unequally becomes a general quadratic).
  312.         (A sphere scaled equally remains a sphere).
  313.  
  314.     a_shape = rot_x(a_shape,angle)
  315.         Returns a copy of the shape, rotated by angle about the x axis
  316.         Angle is specified in radians
  317.         Similar functions rot_y and rot_z exist
  318.  
  319.     a_shape = union(a_shape,a_shape)
  320.         Returns a shape which is the CSG union of the two shapes
  321.         Similar functions isect, diff, sdiff and extent exist
  322.         sdiff means symmetric difference (like XOR)
  323.         extent is explained later
  324.  
  325.     a_shape = resurf(a_shape,a_surf)
  326.         Returns a shape with the same geometry as before, but with
  327.         different surface characteristics
  328.  
  329. The commands supported in the language take a number of rvalues as arguments.
  330. These arguments are space seperated.
  331.  
  332.     set_value a_new_value a_value
  333.         Defines a variable a_new_value to be the value a_value
  334.         eg: set_value door_width 34.5
  335.  
  336.     set_xyz a_new_xyz a_xyz
  337.         Defines a vector
  338.         eg: set_xyz viewpoint xyz(1.0,3.5,10.2)
  339.  
  340.     set_rgb a_new_rgb a_rgb
  341.         Defines a RGB colour vector
  342.         eg: set_rgb yellow rgb(1,1,0)
  343.  
  344.     set_col a_new_col a_col
  345.         Defines a new colour structure
  346.  
  347.     set_surf a_new_surf a_surf
  348.         Defines a new surface structure
  349.         eg: set_col shiny_red col(0.2,0.6,0.2,0.0,
  350.                       col(rgb(1.0,0.0,0.0)),
  351.                       col(rgb(1.0,1.0,1.0)),
  352.                       200,1)
  353.  
  354.     set_shape a_new_shape a_shape
  355.         Defines a variable a_new_shape to be the shape a_shape
  356.         a_shape is anything that evalues to a shape
  357.         eg: set_shape shell diff(sphere(2,a_surf),sphere(1,a_surf))
  358.  
  359. If you have set a variable using the above, then it can itself be used as a
  360. rvalue.
  361.  
  362. eg: set_shape ball sphere(2.0,greeny_blue)
  363.     set_shape earth ball
  364.  
  365. Other commands are as follows :-
  366.  
  367.     set_attenuation af1 af2
  368.         Set light intensity with distance coefficents
  369.         The nature of this equation and its parameter is arbitrary
  370.         This function is likely to change later
  371.         Defaults to 1.0 and 0.9 at present
  372.         The 0.9 means that light intensity fades to 90%, per unit
  373.         distance travelled.
  374.  
  375.     set_background a_rgb
  376.         Sets background light intensity
  377.         Defaults to rgb(0,0,0) at present
  378.         Used when no object is struck by light ray.
  379.  
  380.     set_ambient a_rgb
  381.         Sets ambient light intensity
  382.         Defaults to rgb(0,0,0) at present
  383.         eg: set_ambient shiny_red
  384.  
  385.     add_light a_xyz a_rgb
  386.         Adds a light at specified position of given intensity
  387.         No lights exist before the first add_light found
  388.         Lights cannot be removed in present implementation
  389.         eg: add_light xyz(1,1,1) rgb(1,1,0)
  390.  
  391.     render shape eye forward up hangle vangle hpixels vpixels depth
  392.       rendertype "filename"
  393.         Renders a view of shape
  394.         View is from the eye position, looking forward
  395.         The up vector used to decide which way is up
  396.         hangle and vangle specify angles of viewing pyramidal volume
  397.         hpixels and vpixels specify size of output bitmap
  398.         extra depth to recurse to
  399.         rendertype is 0 for a typical simple render operation.
  400.         rendertype is 1 for an anti-aliased trace.
  401.         "filename" is the output bitmap filename
  402.  
  403.     visdiff a_value
  404.         Set minimum visible difference value used in anti-aliasing
  405.         computation. Default is 1.0/255.0.
  406.  
  407.     include "filename.rt"
  408.         Causes the given file to be read in and processed.
  409.         Ideal for when you put an object in an .rt file and then
  410.         wish to use it from another .rt file.
  411.  
  412.  
  413. A complicated example
  414. ---------------------
  415.  
  416. We have a bitmap of the surface of the earth. It is 360 x 180 pixels and
  417. pixel (180,90) is longitude 0 degrees at the equator.
  418.  
  419.     set_col col1 col_field2d(180,90,"map.bmp")
  420.  
  421. When col1 is evaluated p0 and p1 are indexed into the bitmap as x and y to
  422. give the colour of the earth at a longitude of p0 and latitude of p1.
  423. A half-plane aligned along the x-y plane drawn in this colour would show
  424. a map of the world.
  425.  
  426.     set_col col2 col_interp0(col_interp1(col1))
  427.  
  428. When you look close-up at something drawn in colour col1, you may be able
  429. to see the pixel boundarys. col2 does not suffer from this so badly, as linear
  430. interpolation has been used to smooth the pixels in both directions.
  431.  
  432.     set_col col3 col_sph(rad(1),rad(1),1,col2)
  433.  
  434. When col3 is evaluated p0,p1 and p2 are mapped from x,y,z coordinates to
  435. a longitude, latitude and radius from the origin. The longitude is divided by
  436. rad(1) to give a p0 which is the multiple of 1 degree increments. Similarly
  437. for the latitude for p1. The radius is divided by 1 (ignored) for p2.
  438. ie: we will chain-on to evaluate col1 with p0 equal to the number of degrees
  439. east of Grenwich and p1 equal to the number of degrees above the equator.
  440. A sphere at the origin drawn in this colour would display a map of the world
  441. drawn on the sphere, much like a real globe.
  442.  
  443.     set_surf surf1 surf(...,col3...)
  444.         ; other arguments to surf omitted for clarity
  445.     set_shape shape1 sphere(1.0,surf2)
  446.  
  447. This defines a sphere, at the origin, which is drawn in a colour that is a
  448. map of the world.
  449.  
  450.     set_shape shape2 trans(shape1,xyz(0.5,0.1,0.2))
  451.  
  452. This the same as shape1, only the origin of the globe is at (0.5,0.1,0.2).
  453. The colour of this shape has also moved so that the continents of the world
  454. still sit on the correct parts of the surface of the sphere.
  455.  
  456.     set_surf surf2 surf(...,col_nomove(col3),...)
  457.     set_shape shape3 sphere(1.0,surf2)
  458.  
  459. This is an awkward shape. Although this would render identically to shape1,
  460. should you apply the trans() or rot_x() operator to it, only the shape, not
  461. the 2d bitmap texture would move!
  462.  
  463.  
  464. The 'extent' CSG operator
  465. -------------------------
  466.  
  467. Operators such as union(shape_a,shape_b) conceptually tell the ray-tracer to
  468. intersect a ray with shapes shape_a and shape_b. This gives an intersection
  469. list which says where the ray enters and leaves shape_a, and another which
  470. says where the ray enters and leaves shape_b. By combining these intersection
  471. lists we can deduce where the ray enters and leaves the CSG union of shapes
  472. shape_a and shape_b.
  473.  
  474. In practice the ray tracer can make certain optimisations. For example if we
  475. are tracing isect(shape_a,shape_b) and the intersection list generated for
  476. one of the shapes is empty (does not go through anything) then the result must
  477. also be the empty set. ie: nothing intersected with something is nothing.
  478.  
  479. This type of optimisation allows the ray-tracer to avoid calculating ray
  480. intersections for certain parts of the shape tree.
  481.  
  482. The extent(shape_a,shape_b) operator only intersects with shape_a, if the
  483. intersection with shape_b is non null. This is particularly useful when shape_b
  484. is made to enclose shape_a, and shape_a is difficult (complicated) to intersect.
  485.  
  486. For example, if I had a scene with a dice (made of many primitives) in one
  487. small part of it. I could use extent(shape_dice,shape_enclosing_sphere) to
  488. speed up the tracing. The assumption here is that a sphere is much quicker to
  489. calculate intersections for than some complicated CSG shape such as a
  490. dice (which may have 6 half-plane faces, a rounding sphere and 1+2+3+4+5+6
  491. spheres for spots subtracted etc!). The other assumption is that most of the
  492. time we will not be tracing the part of the picture with the dice in.
  493.  
  494.  
  495. Antialiasing
  496. ------------
  497.  
  498. This ray tracer has 2 modes (or rendertypes) in which it can trace pictures.
  499.  
  500. Mode 0 is a simple point sample trace, which as a result can exhibit
  501. severe aliasing.
  502.  
  503. Mode 1 is an antialiased trace, which significantly cuts down on aliasing.
  504. Because the Whitted adaptive supersampling technique is used, the penalty of
  505. tracing additional rays is only paid where adjacent pixels differ notably.
  506. 'Notably' is a little vague, and is specified by the visdiff command.
  507.  
  508. Raytracing produces floating point intensities for each ray traced. These must
  509. be mapped to byte values to be written into the file. So the range of
  510. intensities from 0.0 to 1.0 map to byte values 0 to 255.
  511.  
  512. Therefore the minimum visible difference is 1.0/255.0. This is the default
  513. visdiff value.
  514.  
  515. However, if the 2 least significant bits of a byte are not required to be
  516. significant, then the visdiff value can be raised to 1.0/63.0. If the final
  517. output file is to be displayed on VGA hardware, this would be ideal.
  518.  
  519. Raising the visdiff value reduces the number of extra rays that are traced
  520. due to adjacent samples being different colours, because fewer adjacent
  521. will exceed the higher visdiff difference value. One testcard requires
  522. 13x the basic cost to trace with the default visdiff, but only 6x with the
  523. higher visdiff value above.
  524.  
  525. Other rendertypes, such as 'always-supersample' may be added later.
  526.  
  527.  
  528. Escher Perspective Rendering
  529. ----------------------------
  530.  
  531. By adding in 10 to the rendertype described above it is possible to tell the
  532. Ray Tracer to trace in the wide (or should I say tall) angle style of
  533. projection that M.C.Escher did in his "Above and Below" and "House of Stairs"
  534. woodcuts.
  535.  
  536.  
  537. Limitations of the refraction system
  538. ------------------------------------
  539.  
  540. I unconditionally admit that my CSG refraction code is a hack.
  541.  
  542. In a CSG system, a point in space is empty or solid. To model refraction
  543. effectively a point in space is empty (a transmissive medium with a refractive
  544. index) or solid (non-transmissive medium). This means we should have many
  545. classifications of points in space.
  546.  
  547. It is difficult to define boolean CSG operations on multivalue types. eg:
  548. what does it mean if a medium of index 1.5 intersects a medium of index 1.3?
  549.  
  550. This program implements refraction by making a set of assumptions. Firstly, it
  551. is assumed that the refractive index of empty space is 1.0. Certain solid
  552. objects can be considered to have other indexes.
  553.  
  554. All the surfaces that define the boundary of a transmissive shape should have
  555. a non-zero transmissive coefficient (ideally the same). This states how much
  556. of the light from the other side of the shape is to be allowed through.
  557. If the coefficients are not the same, you can produce shapes that look
  558. brighter from some directions.
  559.  
  560. Also the surfaces should all have a refractive index set (ideally the same).
  561. This refractive index is used to bend rays into the shape, and out again.
  562. If the refractive indexes are not the same, you can produce shapes that have
  563. different optical properties when viewed from certain directions. This
  564. actually is contradictory to the physics being modelled!
  565.  
  566. When a ray strikes a transmissive surface the following additional work is
  567. done. If total external reflection occurs then an additional reflected ray is
  568. spawned (this is unlikely, as it implies the tranmissive solid has a
  569. refractive index < 1.0, and most things don't - glass=1.5, water=1.3 etc.).
  570. Otherwise a refracted ray is sent through the solid until it emerges at the
  571. far side. If total internal reflection occurs at the far side, the ray is
  572. bounced back into the object again. Eventually the ray is refracted out into
  573. empty space. The emerging rays intensity is of course, scaled by the
  574. additional distance spent going through the solid object, and by kt of each
  575. surface the ray enters the shape by.
  576.  
  577. There is a limit to the number of internal bounces allowed due to total
  578. internal reflection. This limit is around 10 bounces. If this limit is exceeded
  579. the refraction computation is aborted.
  580.  
  581. Due to the way CSG systems merge shapes into one compound shape, certain
  582. problems can be produced. For example, if you place a large glass slab onto a
  583. smaller red block, you will find that the side faces of the red block, seen
  584. from above through the glass block are red, but the top of the red block is
  585. not!
  586.  
  587. Why? Well the the two blocks may actually touch to form a composite CSG object.
  588. In the first case, the ray enters the composite object through a glass
  589. surface, leaves the solid via a glass surface, and strikes a red side surface.
  590. In the other case, the ray enters through a glass surface, but leaves through
  591. the bottom red surface of the composite CSG shape. The colour returned is
  592. whatever is beneath the red block. ie: in the diagram, there is no surface
  593. defined at point X to give the expected view of the red top of the block
  594. below the glass block.
  595.  
  596.          ray 1       ray 2
  597.             \          |
  598.      gggggggg\ggggggggg|gggggggggggg
  599.      g        \        |           g    <--- Glass block
  600.      gggggggggg\ggg    X    gggggggg
  601.                 \ r    |    r
  602.                  \r    |    r           <--- Red block
  603.                   rrrrr|rrrrr
  604.                        |
  605.                    ooooooooo            <--- Other shape
  606.  
  607. The simple workaround to this problem is to ensure that the glass block is
  608. just the tiniest amount above the red block, so that the rays leave the glass
  609. before hitting the red block.
  610.  
  611.  
  612. Bitmap formats supported
  613. ------------------------
  614.  
  615. The code will always write out 24 bit bitmaps.
  616. When reading, (for texture maps etc.) 1,4,8 or 24 bit bitmaps can be used.
  617.  
  618. This program utilises the services of the Bitmap Rosetta Stone, the
  619. Generalised Bitmap Module (or GBM for short).
  620.  
  621. GBM supports the reading and writing of a large number of bitmap file formats
  622. in a manner that isolates the calling program (RT) from the format details.
  623.  
  624. Under OS/2 this support is provided by the files GBM.DLL, GBM.LIB, GBM.H and is
  625. documented by the file GBM.TXT, and these files should be included with this
  626. package.
  627.  
  628. The full source to GBM is hopefully available from the same place you obtained
  629. this Ray Tracer. By obtaining the source, versions of GBM for AIX and other 32
  630. bit operating systems may be easily be built. GBM is designed like RT to be
  631. highly portable.
  632.  
  633.  
  634. Nature of bitmap bits
  635. ---------------------
  636.  
  637. The bitmap bits both read and written are written with value proportional to
  638. physical brightness. This means that for OS/2 PM for example, these should be
  639. mapped to/from the L* cyclometric colour space. Similarly, when displaying
  640. the bitmaps on a specific monitor directly, the pixels should be mapped to
  641. a gamma corrected colour space designed to counteract the monitors gamma.
  642. In reality these mappings are often skipped, as the results are very similar.
  643.  
  644.  
  645. 3D Texture map files
  646. --------------------
  647.  
  648. In the absence of a readily available 3D texture map format, I invented one.
  649. The 3D texture map file format is inspired by the OS/2 2.0 bitmap formats :-
  650.  
  651.     typedef unsigned char byte; /* 8 bit number */
  652.     typedef unsigned long dword; /* Intel ordered 32 bit number */
  653.     typedef struct { byte b, g, r, dummy; } PAL; /* Palette entry */
  654.     typedef struct { byte i [(width*bits_per_voxel+31)/32*4]; } SCAN;
  655.  
  656.     typedef struct
  657.         {
  658.         dword 0x1a584554;        /* Magic number */
  659.         dword width, height, depth;    /* x,y and z dimensions */
  660.         dword bits_per_voxel;        /* 1, 4, 8 or 24 only */
  661.         PAL pals [(1<<bits_per_voxel)&0x1ff];
  662.         SCAN scans [depth][height];
  663.         } TEXFILE;
  664.  
  665. The expression inside the [] in the pals array converts 1 -> 2, 4 -> 16,
  666. 8 -> 256 and 24 -> 0, ie: it converts the bits_per_voxel into number of palette
  667. entrys present. Much like OS/2 2.0 bitmaps.
  668.  
  669. The expression inside the SCAN definition ensures each scanline is padded to
  670. the next biggest 32 bit boundary. Also like OS/2 2.0 bitmaps.
  671.  
  672. Scan lines are stored leftmost pixel to rightmost, and they are stored one
  673. after another starting at lowest to highest. Also like OS/2 2.0 bitmaps.
  674. Finally complete 2D images are stored one after each other lowest depth first.
  675.  
  676.  
  677. Intersection lists
  678. ------------------
  679.  
  680. Internally the tracer uses intersection lists as it recursively intersects each
  681. ray with each sub-tree of the shape tree. The raytracer automatically computes
  682. the required number of lists. However, the user may wish to bear in mind that
  683. less deeply nested shape trees require fewer lists, and therefore less memory.
  684.  
  685. Intersections lists hold the entrys and exits from surfaces caused by firing
  686. a ray from a given point in a given direction. An intersection list is
  687. implemented internally as an array, and so has finite size. If a ray
  688. enters/leaves surfaces too many times, the array could be overflown! Early
  689. versions of the raytracer had a fixed limit to the size of an intersection
  690. list. The current version automatically computes the worst case. The result
  691. of the worst case calculation can be significantly higher than the actual
  692. worst case for a given model, so in the future I may provide user override.
  693.  
  694.  
  695. Compilers etc.
  696. --------------
  697.  
  698. AIX 3.1 xlc compiler and should also support any general ANSI UNIX compiler.
  699. IBM C-Set/2 32 bit C compiler for 32 bit OS/2, although slow if no FPU.
  700. IBM C-Set++ 32 bit C/C++ compiler for 32 bit OS/2, although slow if no FPU.
  701.  
  702.  
  703. Relative tracing times (out of date)
  704. ------------------------------------
  705.  
  706. Effect of FPU (20 MHz 386 DX Model 80) :-
  707.  
  708.                 No FPU            16 MHz 387
  709.  
  710. C-Set/2    (with /O- /Gf-)        780:00            17:00
  711. C-Set/2 (with /O- /Gf+)        850:00 approx        16:00
  712.  
  713. Effect of CPU :-
  714.  
  715. 20 MHz 386 DX  Model 80 (with 387 for fairness):    22:00
  716. 33 MHz 486 DX  Model 95 (has FPU built in):         3:35
  717. 50 MHz 486 DX  Model 95 (has FPU, with secondary cache): 2:37
  718. 50 MHz 486 DX2 No-Name clone (has FPU built in):     2:14
  719. RS/6000 520:                         1:20
  720.  
  721.  
  722. Public domain declaration
  723. -------------------------
  724.  
  725. I wrote all this code in my own time on my own equiptment.
  726. I hereby place all this code into the public domain.
  727. Feel free to do whatever you like with it.
  728. No copyright / no royalties / no guarantees / no problem.
  729.  
  730.  
  731. Change Log
  732. ----------
  733.  
  734. 1/1/92        Initial general release.
  735.  
  736. Various dates    Fixed assorted bugs.
  737.         Removed support for 16 bit systems.
  738.         Tidied source to make fussier compilers happy (eg: IBM C-Set++)
  739.         Added support for GBM based bitmap file handling.
  740.         Complete rewrite of colour support.
  741.         Added capability to handle 1,4 and 8bpp bitmap 2D textures.
  742.         Added capability to do 3D block texture maps.
  743.         Improved shape tree memory management.
  744.         Improved intersection list management.
  745.         Added resurface a shape capability.
  746.         Submitted to Internet.
  747.  
  748. 11/1/93        Removed support for non-GBM based bitmap file handling.
  749.         Added biplane shape to accelerate tracing.
  750.         Added of rendertype argument to render command.
  751.         Added Whitted anti-aliased rendering rendertype.
  752.         Added Escher perspective rendering rendertype.
  753.         Submitted to Internet.
  754.  
  755. {{{ Andy Key
  756.  
  757. Internet: ak@vnet.ibm.com    # Currently working at IBM until 31st Dec 1993
  758. IBM-VNET: AKEY AT HVTVM5    # so addresses valid at least until then.
  759.