home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1993 #3 / NN_1993_3.iso / spool / comp / graphics / visualiz / 2082 < prev    next >
Encoding:
Text File  |  1993-01-27  |  7.2 KB  |  346 lines

  1. Newsgroups: comp.graphics.visualization
  2. Path: sparky!uunet!nwnexus!paulf
  3. From: paulf@halcyon.com (Paul Forgey)
  4. Subject: Red/Blue 3D with POV
  5. Message-ID: <1993Jan26.233400.10404@nwnexus.WA.COM>
  6. Sender: sso@nwnexus.WA.COM (System Security Officer)
  7. Organization: Northwest Nexus Inc. (206) 455-3505
  8. Date: Tue, 26 Jan 1993 23:34:00 GMT
  9. Lines: 335
  10.  
  11.  
  12. This is a very long message, so remember that 'n' will skip it.
  13.  
  14. I have worked out an exiting method of developing red/blue three dimentional
  15. images with Persistance Of Vision (POVRAY 1.0).  The idea is very simple,
  16. and involves rendering two images:  One for the left eye (red) and the other
  17. for the right eye (blue).  
  18.  
  19. I wrote a simple program which takes two .TGA files, grey sums them, then
  20. makes a master red/blue file out of the two images.  Be sure to keep straight
  21. which is left/red and right/blue!  Otherwise, you will have to wear your 3D
  22. glasses upside down.
  23.  
  24. I haven't bothered to figure out optimal ratios for camera distance, but I 
  25. can tell you that with the following camera:
  26.  
  27. camera {
  28.   location <0 1 -3>
  29.   direction <0 0 1.5>
  30.   up <0 1 0>
  31.   right <1.33 0 0>
  32.   look_at <0 1 2>
  33. }
  34.  
  35. The left  image would be location <-0.05 1 -3>
  36. The right image would be location <0.05 1 -3>
  37.  
  38. A distance of 0.1 apart seems to work well.  For lower resolutions, the
  39. location should never be exactly in-line with the look_at parameter.
  40.  
  41. The best way to accomplish this is to have a "leftcam.pov" and a
  42. "rightcam.pov", both of which include a "common.pov" which holds objects
  43. common to both eyes (generally this is everything except your cameras).
  44.  
  45. The following is a really nifty demonstration of this effect, and a single
  46. frame of an animation I am working on.
  47.  
  48. -source code for TGAMIX.EXE follows:  
  49.  
  50. (Written in Borland C++ 3.1, should work with most other platforms)
  51.  
  52.  
  53. #include <stdio.h>
  54. #include <process.h>
  55. #include <fcntl.h>
  56. #include <io.h>
  57.  
  58. typedef unsigned char BYTE;
  59.  
  60. typedef struct 
  61. {
  62.   BYTE     ID;
  63.   BYTE     ColorMapType;
  64.   BYTE     ImageType;
  65.   unsigned FirstColorMapEntry;
  66.   unsigned ColorMapLength;
  67.   BYTE     ColorMapEntrySize;
  68.   unsigned XOrigin;
  69.   unsigned YOrigin;
  70.   unsigned Width;
  71.   unsigned Height;
  72.   BYTE     BitsPerPixel;
  73.   BYTE     ImageDescriptorBits;
  74. } imagedata;
  75.  
  76. typedef struct 
  77. {
  78.   BYTE Blue;
  79.   BYTE Green;
  80.   BYTE Red;
  81. } RGB24;
  82.  
  83. void OpenTGAFile(const char *, int *, imagedata *);
  84. void OpenTargetFile(const char *, int *, imagedata *);
  85. void ProcessLine(int, int, int, unsigned);
  86. void ProcessImages(const char *, const char *, const char *);
  87.  
  88. // open a TGA file, check it's type, return the data.
  89. // if unable to handle it, or error, exits to OS
  90. void OpenTGAFile(const char *filename, int *handle, imagedata *data)
  91. {
  92.   *handle = open(filename, O_RDONLY | O_BINARY);
  93.   if (*handle == -1)
  94.   {
  95.     fprintf(stderr, "\nCannot open %s for reading\n", filename);
  96.     exit(1);
  97.   }
  98.  
  99.   read(*handle, data, sizeof(imagedata));
  100.  
  101.   if (data->ImageType != 2 || data->BitsPerPixel != 24)
  102.   {
  103.     printf("\nImages must be type 2 (true color, uncompressed).\n"
  104.            "(If this is the case, be sure file is 24-bit)\n");
  105.     exit(1);
  106.   }
  107.  
  108.   if (data->Width > 1024)
  109.   {
  110.     printf("\nImages must be no more than 1024 pixels wide.\n");
  111.     exit(1);
  112.   }
  113. }
  114.  
  115. // opens the target file, writing data as a header
  116. void OpenTargetFile(const char *filename, int *handle, imagedata *data)
  117. {
  118.   *handle = open(filename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC); 
  119.   if (*handle == -1)
  120.   {
  121.     fprintf(stderr, "\nCannot open %s for writing\n", filename);
  122.     exit(1);
  123.   }
  124.  
  125.   write(*handle, data, sizeof(imagedata));
  126. }
  127.  
  128.  
  129. // reads a line from red and blue, sums the colors, then writes the
  130. // composite to output
  131. void ProcessLine(int red, int blue, int output, unsigned width)
  132. {
  133.   static RGB24 redBuffer[1024];
  134.   static RGB24 blueBuffer[1024];
  135.   static RGB24 outBuffer[1024];
  136.   unsigned i;
  137.  
  138.   read(red, redBuffer, width * sizeof(RGB24));
  139.   read(blue, blueBuffer, width * sizeof(RGB24));
  140.  
  141.   for (i=0; i < width; ++i)
  142.   {
  143.     outBuffer[i].Green = 0;
  144.     
  145.     outBuffer[i].Red =  (BYTE)(0.30 * (double)(redBuffer[i].Red) +
  146.                                0.59 * (double)(redBuffer[i].Green) +
  147.                                0.11 * (double)(redBuffer[i].Blue));
  148.  
  149.     outBuffer[i].Blue = (BYTE)(0.30 * (double)(blueBuffer[i].Red) +
  150.                                0.59 * (double)(blueBuffer[i].Green) +
  151.                                0.11 * (double)(blueBuffer[i].Blue));
  152.  
  153.   }
  154.  
  155.   write(output, outBuffer, width * sizeof(RGB24));
  156. }
  157.  
  158. // does the whole damn thing
  159. void ProcessImages(const char *redFile, 
  160.                    const char *blueFile,
  161.                    const char *outFile)
  162. {
  163.   static imagedata redData;
  164.   static imagedata blueData;
  165.   unsigned width, height, i;
  166.   int redHandle, blueHandle, outHandle;
  167.  
  168.   OpenTGAFile(redFile, &redHandle, &redData);
  169.   OpenTGAFile(blueFile, &blueHandle, &blueData);
  170.  
  171.   if (redData.Width != blueData.Width)
  172.   {
  173.     printf("\nRed and Blue files must be of the same width.\n");
  174.     exit(1);
  175.   }
  176.  
  177.   OpenTargetFile(outFile, &outHandle, &redData);
  178.  
  179.   width = redData.Width;
  180.   height = redData.Height;
  181.  
  182.   for (i = 0; i < height; ++i)
  183.   {
  184.     ProcessLine(redHandle, blueHandle, outHandle, width);
  185.   }
  186.  
  187.   close(redHandle);
  188.   close(blueHandle);
  189.   close(outHandle);
  190. }
  191.  
  192.  
  193. void main(int argc, char **argv)
  194. {
  195.   if (argc < 4)
  196.   {
  197.     printf("\nUsage:\n");
  198.     printf("%s redfile bluefile outfile\n", argv[0]);
  199.     exit(0);
  200.   }
  201.  
  202.   ProcessImages(argv[1], argv[2], argv[3]);
  203. }
  204.  
  205. The rest of the files may seem complicated, but this is a frame of an 
  206. animation with common and frame specific objects
  207.  
  208. -following is leftcam.pov
  209.  
  210. camera {
  211.   location   <-0.05 1 -3>
  212.   direction  <0 0 1.5>
  213.   up         <0 1 0>
  214.   right      <1.33 0 0>
  215.   look_at    <0 1 2>
  216. }
  217.  
  218. -following is rightcam.pov
  219.  
  220.  
  221. camera {
  222.   location   <0.05 1 -3>
  223.   direction  <0 0 1.5>
  224.   up         <0 1 0>
  225.   right      <1.33 0 0>
  226.   look_at    <0 1 2>
  227. }
  228.  
  229.  
  230. -following is common.pov
  231.  
  232.  
  233. #include "colors.inc"
  234. #include "shapes.inc"
  235. #include "textures.inc"
  236.  
  237. object {
  238.   light_source { 
  239.     <2 4 -3> 
  240.     color 
  241.       White 
  242.   }
  243. }
  244.  
  245. object {
  246.   light_source {
  247.     <-2 4 -3>
  248.     color
  249.       White
  250.   }
  251. }
  252.  
  253. object {
  254.   plane { 
  255.     <0 1 0> 0
  256.   }
  257.   texture {
  258.     checker
  259.       color White
  260.       color Black
  261.   }
  262. }
  263.  
  264. -following is frame1l.pov (frame 1, left image)
  265.  
  266.  
  267. #include "left.pov"
  268.  
  269. object {
  270.   sphere {
  271.     <0 1 1> .5
  272.     texture {
  273.       color Grey
  274.       phong 1
  275.     }
  276.   }
  277. }
  278.  
  279. object {
  280.   sphere {
  281.     <1.5 1.5 2> .5
  282.     texture {
  283.       color Grey
  284.       phong 1
  285.     }
  286.   }
  287. }
  288.  
  289. object {
  290.   sphere {
  291.     <0 2 3> .5
  292.     texture {
  293.       color Grey
  294.       phong 1
  295.     }
  296.   }
  297. }
  298.  
  299. object {
  300.   sphere {
  301.     <-1.5 1.5 2> .5
  302.     texture {
  303.       color Grey
  304.       phong 1
  305.     }
  306.   }
  307. }
  308.  
  309. -to create frame1r.pov, simply #include "right.pov" instead of "left.pov"
  310. in the preceeding.
  311.  
  312. -the following is left.pov
  313.  
  314.  
  315. #include "common.pov"
  316. #include "leftcam.pov"
  317.  
  318. -to create right.pov, simply #include "rightcam.pov" instead of "left.pov"
  319.  
  320.  
  321. -the following is BUILD.BAT, an MS-DOS batch file to assemble the entire
  322. mess
  323.  
  324.  
  325. povray -iframe1l.pov -oleft1.tga
  326. povray -iframe1r.pov -oright1.tga
  327. tgamix left1.tga right1.tga data1.tga
  328. pl286 2gif data1
  329.  
  330. -and finally, the PicLab script to convert a tga to a gif:
  331.  
  332. tload %1.tga
  333. makepal
  334. map
  335. gsave %1.gif
  336.  
  337.  
  338. Please notice there is a minimum of command line options.  Read the
  339. documentation for POVRAY and modify your environment variable or POVRAY.DEF
  340. file accordingly.
  341.  
  342. Have fun.
  343.  
  344. Paul Forgey
  345. paulf@halcyon.com
  346.