home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / rayce27s / tech.doc < prev    next >
Encoding:
Text File  |  1994-01-20  |  13.5 KB  |  453 lines

  1. -*-text-*-
  2.  
  3. Hi There!
  4.  
  5. This is supposed to be a more detailed doc file about the technicalities
  6. of Rayce. It is under construction (as is everything in Rayce :-)
  7.  
  8.  
  9.     ABOUT THE SOURCES
  10.  
  11. I've tried to continue the Ray-tradition: I've commented the sources
  12. to my best ability, and I hope I didn't obfuscate the sources too
  13. much. All sources have been formatted with GNU indent (see the file
  14. cformat).  I have always use 132 x 43 screen resolution, so some of
  15. the source will not be very readable in 80x25....  Get yourself a
  16. serious VGA card :)
  17.  
  18.  
  19.     COMPILING
  20.  
  21. Remember these if you attempt at compiling Rayce:
  22.  
  23. 0. Get a ANSI compliant compiler. I don't know wether it will compile
  24. on non ANSI compilers, but it will undoubtedly give problems.
  25.  
  26. 1. I've tried to keep all device/compiler dependent stuff in a
  27. separate file.  generic version of this file is in dvi.c; it provides
  28. only the stubs for the functions.
  29.  
  30. If you want to port Rayce, then make a new Makefile and a replacement
  31. for the systemfile. look at ibmtcc.c or linux.c to see which functions
  32. it should have, and what they should do.  It would be nice if you sent
  33. me a copy of the source, and the makefile.  If you are very lazy, you
  34. can use dvi.c. The linux.c file only uses ANSI standard routines, so
  35. you should be able to use linux.c for most OSes which have signals.
  36.  
  37. These files are provided:
  38.  
  39.   - makefile.tcc, ibmtcc.c: for Turbo/Borland-C++ 
  40.   - Makefile, linux.c: for Linux
  41.   - makefile.dj, djgcc.c: for DJGCC (the port was done by Shawn
  42.   McHorse <Zaphod@fcircus.sat.tx.us>)
  43.  
  44.  
  45. 2. Although I tried to avoid system dependent code outside the
  46. systemfiles, there are some exceptions:
  47.  
  48. - the naming of MS Dos is somewhat braindead, so in token.c, there is
  49. a bit of conditional compilation for including "rayparse.h" instead of
  50. "rayparse.tab.h" under MSDOS.
  51.  
  52. - in rayparse.y it says
  53.  
  54.     #ifdef __TURBOC__
  55.     #define alloca allocaa
  56.     #endif
  57.  
  58. 3. Make sure that Rayce has enough memory.  In MSDOS this means: a
  59. reasonable stack size, and a large memory model.  Turbo C's 4k stack
  60. is definitely too small, but 16k suffices.
  61.  
  62. 4. Get some variant of Yacc. I use Bison, but any other Yacc will
  63. probably also work. If you use Bison, and your compiler has no
  64. alloca() function, you'd better define alloca to be allocaa in
  65. rayparse.y.  Turbo C doesn't have alloca(), so I made a fix: memory
  66. obtained allocaa() is freed after yyparse() has exited.
  67.  
  68. 5. If you use Linux, it is very easy, just type
  69.  
  70.     make srayce
  71.  
  72. for a speedy version of Rayce.
  73.  
  74.  
  75.     SOURCE DESCRIPTION
  76.  
  77. *    ray.h
  78.  
  79. typedefs and important #defines  for rayce.
  80. The most important ones:
  81.     
  82. object: This is the main structure. It holds shape data, textures,
  83. boundingshapes. It has a "next" field, so it can easily be linked into
  84. a linked list.
  85.  
  86. struct ray: this is (of course the ray.) it is a line, starting at
  87. ray.pos, headed for ray.dir.
  88.  
  89. A few important notes:
  90.  
  91. If you want to study the sources of Rayce, you'd better start reading
  92. here.
  93.  
  94. A function or variabele that is local to a file is called PRIVATE.  A
  95. function or variabele that can be accessed from the whole program is
  96. called PUBLIC. 
  97.  
  98. The vector as well as the color are structs, not arrays, so they must
  99. be passed by pointer, if function wants to change them. But the
  100. advantage is, they can be returned from a function.
  101.  
  102. *    object.h
  103.  
  104. struct xxxx_data: a structure which holds info on shapes, textures,
  105. etc. eg. sphere_data contains a radius and a center.
  106.  
  107. *    proto.h
  108.  
  109. function prototypes, to avoid the compilers' weird ideas about
  110. default prototyping. Modifying its contents usually is harmless, so
  111. the makefile just ignores it.
  112.  
  113. *    extern.h
  114.  
  115. Global variables.  Because this header is included more than once, all
  116. variables have been declared as EXTERN, which is defined as extern.  In
  117. initialize.c, EXTERN is undef'ed, and included again.  So storage for
  118. global variables is only allocated once. Important ones: commandline
  119. options, statistics.
  120.  
  121. *    parse.h
  122.  
  123. for communication between rayparse and token.
  124.  
  125. *    rayparse*.h
  126.  
  127. This one is generated by bison.  It contains token codes and the token
  128. types.
  129.  
  130. *    rayparse.y
  131.  
  132. The Bison sources for the parser. Bison generates:
  133.  
  134. *    rayparse.c or rayparse.tab.c
  135.  
  136. from rayparse.y. I don't distribute the file, because you can generate
  137. it yourself in a few seconds.
  138.  
  139. *    vector.h
  140.  
  141. Vector functions. They usually have this form
  142.  
  143.   vectormacro(output, input1, input2).
  144.  
  145. Take care: usually a construction like vsub(a,a,b) (equivalent with
  146. a:=a-b) works fine, but you can't do this with vcross.
  147.  
  148. [Yes. I know, GCC allows inline functions, but I don't want to go
  149. through all the hassle and compiler dependent code.]
  150.  
  151. *    macro.h
  152.  
  153. Other useful macros.
  154.  
  155. If you want to add code, and you want to pull the brakes somewhere.
  156. (for instance a default of a switch(){} that should not occur), then
  157. call thunk().  It prints a neat errormsg, with the file and linenumber
  158. where the error occurred.
  159.  
  160. *    token.c
  161.  
  162. Tokenizer, it contains errormsg(), warning(), it handles includes and
  163. allocation of declares.  The most important function is yylex(). The
  164. rest are little bits. If you add keywords to the syntax, then add it
  165. into the big table in this file. I hardly look at it these days.
  166.  
  167. *    rayparse.y
  168.  
  169. The Yacc/Bison file.  Run "bison -d rayparse.y" to get rayparse_tab.c and
  170. rayparse_tab.h.  On MSDOS systems these names will be truncated to
  171. rayparse.c and rayparse.h.
  172.  
  173. *    raymath.c
  174.  
  175. Linear algebra and simple mathematics:  vector math, matrix math, random
  176. generators.
  177.  
  178. *    ibmtcc.c
  179.     linux.c
  180.     djgcc.c
  181.     dvi.c
  182.  
  183. Compiler/system specific parts: timing, handlers, abort checks.
  184. Although they are still pretty portable, you could substitute dvi.c
  185. for this one, if your compiler has complaints. If you would like to
  186. code display routines, this is where you should add them. I myself
  187. don't like device dependent stuff in a program which is supposed to be
  188. highly portable.
  189.  
  190. *    main.c
  191.  
  192. The file containing main(), it scans the command line, prints notices,
  193. calls the parser and starts the tracing process. (somebody told, I
  194. wasn't careful with scanning the command line, and that it would cause
  195. problems on Atari/Amiga computers. Anybody? )
  196.  
  197. *    trace.c
  198.  
  199. Sets up the tracer, walks all the pixels, and calls trace() for each
  200. pixel.  Ray sampling is done here, and stat printing is done here too.
  201.  
  202. *    intersect.c
  203.  
  204. Small file with main intersection routine:  it does the intersection
  205. with the whole scene, and then fills in the details such as intersection
  206. points, normals. The shadow test is a seperate routine, because it has
  207. to deal with shadow caching, early exit for blocking objects, etc.
  208.  
  209. *    initialize.c
  210.  
  211. Initialization and stuff which I can't put somewhere else. Global
  212. storage allocation.
  213.  
  214. *    bg.c
  215.  
  216. Compute a background color, maybe too small to be a separate file, and
  217. too fancy.  Who needs gradient background?
  218.  
  219. *    poly.c
  220.  
  221. Manipulations of polynomials in one variabel: addition,
  222. multiplication, negation, power, etc. Used by solve.c and algebraic.c.
  223. NB. If you want to do q(x) := q(x) - t(x), then poly_sub(q, q, t) is
  224. OK. But poly_multiply(q,q,t) for q := q*t is not!
  225.  
  226. *    solve.c
  227.  
  228. Solve polynomial equations of arbitrary order.  NB.  The sturm
  229. sequence code isn't fully tested.  It's main entry point is the
  230. function solve_rt_poly() which finds positive roots of a polynomial,
  231. and puts them sorted in an array. If possible, solve_rt_poly uses fast
  232. root finders for 3rd and 4th order equations. If you want to have
  233. accurate results, use sturm_solve_rt_poly().
  234.  
  235. The code was done by the collective Eric H Echidna (who have written a
  236. nice raytracer called Art). I also added bits of myself and Graphics
  237. Gems.
  238.  
  239. *    shade.c
  240.  
  241. Compute the color of a ray using textures, light_sources etc.  This
  242. used to be the best preserved part of the original Ray raytracer.
  243. But Shawn McHorse revised it completely to allow TIR, microfacets, etc.
  244. This file recursively calls trace().
  245.  
  246. *    imagemap.c
  247.  
  248. Stuff for imagemaps:  reading TGAs, mapping planes onto various shapes,
  249. and (of course) standard methods.
  250.  
  251. *    gif.c
  252.  
  253. A file snatched from a Linux Gif viewer. It was created by Harm
  254. Hanemaayer <hhanemaa@cs.ruu.nl>, and it was based on posting in
  255. rec.games.programmer in spring of 1993.
  256.  
  257. *    queue.c
  258.  
  259. This implements a simple depth queue for keeping intersection
  260. information. Who knows how to do priority queues? I would like some
  261. books/articles on the subject.
  262.  
  263. *    texture.c
  264.  
  265. Texture manipulations. This one will be the focus for the next release.
  266.  
  267. *    camera.c
  268.  
  269. Routines for manipulating cameras. Not very useful, tho. It is being
  270. reworked right now.
  271.  
  272. -----------------------------------------------------------------------
  273.  
  274. The files below are files with object and shape standard_routines. The
  275. file xxx.c usually contains:
  276.  
  277.     free_xxx()    free a xxx structure (and it's components)
  278.     get_new_xxx_object()    alloc and init a xxx structure (don't alloc
  279.             components)
  280.     rotate_xxx(),
  281.     scale_xxx(),
  282.     translate_xxx()    transform a xxx structure
  283.  
  284.     all_xxx_intersections()
  285.             intersect a ray with a xxx structure, and put
  286.             some or all intersections into a queue. Give
  287.             info, wether ray.pos is inside shape.
  288.  
  289.     xxx_normal    the normal to a xxx shape.
  290.     copy_xxx    copy a xxx structure (and it's components)
  291.     inside_xxx    is a point inside an xxx shape?
  292.     precompute_xxx    Compute constants for a certain object before
  293.             tracing has started, but after the parsing
  294.             objects should be automatically bounded here.
  295.  
  296. These routines are stored in a method structure. With each instance of a
  297. XXX, a pointer to XXX's methods is stored. So a sphere object carries
  298. a pointer to its own special routines. These routines can only be
  299. accessed using this method structure, since the routines are PRIVATE.
  300.  
  301. If you want to add your own primitive this is what you have to do:
  302.  
  303. - Make your own routines, and put them into a seperate file.  Take a
  304. look at the implementation of some simple shapes, such as polygon, or
  305. sphere. Use stub.c as a starting point.
  306.  
  307. - Add the datastructures to objects.h
  308.  
  309. - define the syntax of your primitive, and please make it PoV like.
  310. Add it to the csg_shape_block or the shape_block. Add the keywords to
  311. token.c and rayparse.y, remember to add support for declarations too.
  312. Here are fragments to get you started:
  313.  
  314. /* rayparse.y */
  315.  
  316. /* token declarations */
  317. %type <objectval> XXXX_block    XXXX_body
  318. %token     XXXX_T
  319. %token <dectabptr> XXXX_IDENTIFIER 
  320.  
  321.  
  322. /* syntax */
  323. XXXX_body: /* how to specify a XXXX */             {
  324.         $$ = get_new_XXXX_object();
  325.         
  326.         /* no precomputation! */
  327.           }
  328.               | XXXX_IDENTIFIER        {
  329.             $$ = get_new_XXXX_object();
  330.         copy_object($$, (object *) $1->data);
  331.           }
  332.           | XXXX_body TRANSLATE vexp    { translate_object($$, $3); }
  333.           | XXXX_body ROTATE vexp     { matrix rm; make_rotation_matrix(rm,$3);rotate_object($$, rm); }
  334.           | XXXX_body scale_stuff        { scale_object($$, $2); }
  335.           | XXXX_body INVERSE        { $$->inverted = !$$->inverted; }
  336.           | XXXX_body texture_block    { $$->text = $2; }
  337.           ;
  338.  
  339.  
  340. XXXX_block: XXXX_T '{' XXXX_body '}'    { $$ = $3; }
  341.         ;
  342.  
  343. /* declarations */
  344. declare_block:
  345.     /* stuff. .. */
  346.     | DECLARE any_identifier '=' XXXX_block    {
  347.         $2->data = (void*) $4;
  348.         $2->type = XXXX_IDENTIFIER;
  349.     }
  350.  
  351.  
  352.  
  353.  
  354. /* token.c, keyword table (it's alfabetical) */
  355. {
  356.       :
  357.       :
  358.     XXXX_T, "xxxx",    /* remember! sorted by alphabet */
  359.      :
  360.     :
  361. }
  362.  
  363. - You're finished! Presto! Test your primitive, and then mail the
  364. modified sources to me.
  365.  
  366.  
  367. *    box.c:
  368.  
  369. Boxes. The algorithm is standard. It also contains a public procedure
  370. intersect_rawbox(), for intersecting a ray with an axis aligned box.
  371. This function is public, because it could be used for bounding shapes.
  372.  
  373. *    composite.c:    
  374.  
  375. A composite is just a bunch of objects which can be treated as one.
  376. This makes collective scaling, rotating etc. very easy. Note that in
  377. Rayce, this is something different than a csg union.
  378.  
  379. *    lights.c:    
  380.  
  381. A very simple file with routines for the lights objects. Code to
  382. create a linked list of all the lights in the scene is also here.
  383. This list is needed for efficiently finding the lights in the scene,
  384. in shade.c.
  385.  
  386. *    plane.c:
  387.  
  388. Infinite planes.
  389.  
  390. *    object.c
  391.  
  392. A uniform interface to the various shapes and object types in Rayce.
  393.  
  394. *    quadric.c
  395.  
  396. Code for arbitrary quadrics.
  397.  
  398. *    sphere.c
  399.  
  400. Spheres, the most basic thing in raytracing (along with checkered
  401. floors ;-) (gee, I must do checkers, some time)
  402.  
  403. *      superq.c
  404.  
  405. Superquadrics. It should work now.
  406.  
  407. *    torus.c
  408.  
  409. Toruses. Simple toruses. They can be calculated quite efficiently,
  410. because it is possible to have very tight bounds around them. uses
  411. solve.c to do the equation solving.
  412.  
  413. *    csg.c
  414.  
  415. CSG unions and intersections. Since the code for both overlaps, they
  416. are contained in one file. Mathematically speaking, they are even
  417. equivalent!
  418.  
  419. *    algebraic.c
  420.  
  421. Arbitrary algebraic surfaces. The general idea is: store the
  422. polynomial in terms of operations (similar to hoc level 4, in The Unix
  423. Programming Environment, by Kernighan & Pike).  Then use a simple
  424. "virtual" stack machine to calculate the resulting polynomial in the
  425. ray parameter t. The normal is calculated in a similar fashion: the
  426. input is vector Loc, and of all operands (which are polynomials p_j),
  427. the polynomial p_j(x1,x2,x3) in Loc is evaluated, and the polynomial
  428. dp_j/dx_i (i = 1..3) is evaluated in Loc. We then get the gradient of
  429. the polynomial Phi(x,y,z) which determines the surface normal
  430.  
  431. *    polygon.c
  432.  
  433. Convex flat polygons. Implemented by clipping a plane with the edges
  434. of a polygon. The polygon is projected onto a coordinate plane before
  435. it is clipped.  I should build an extra routine for non-convex polygons.
  436.  
  437. *    extrusion.c
  438.  
  439. Extrusions. This takes the intersection of a shape with the XY plane,
  440. and then "thickens" it along the Z axis. I have thought of the
  441. algorithm myself, but it turns out mr. Kajiya already did before me.
  442.  
  443. *    triangle.c
  444.  
  445. Smooth and non-smooth triangles. It works by decomposing an
  446. intersection point into barycentric coordinates.
  447.  
  448. /* eof */
  449.  
  450.  
  451.  
  452.  
  453.