home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.graphics.visualization
- Path: sparky!uunet!nwnexus!paulf
- From: paulf@halcyon.com (Paul Forgey)
- Subject: Red/Blue 3D with POV
- Message-ID: <1993Jan26.233400.10404@nwnexus.WA.COM>
- Sender: sso@nwnexus.WA.COM (System Security Officer)
- Organization: Northwest Nexus Inc. (206) 455-3505
- Date: Tue, 26 Jan 1993 23:34:00 GMT
- Lines: 335
-
-
- This is a very long message, so remember that 'n' will skip it.
-
- I have worked out an exiting method of developing red/blue three dimentional
- images with Persistance Of Vision (POVRAY 1.0). The idea is very simple,
- and involves rendering two images: One for the left eye (red) and the other
- for the right eye (blue).
-
- I wrote a simple program which takes two .TGA files, grey sums them, then
- makes a master red/blue file out of the two images. Be sure to keep straight
- which is left/red and right/blue! Otherwise, you will have to wear your 3D
- glasses upside down.
-
- I haven't bothered to figure out optimal ratios for camera distance, but I
- can tell you that with the following camera:
-
- camera {
- location <0 1 -3>
- direction <0 0 1.5>
- up <0 1 0>
- right <1.33 0 0>
- look_at <0 1 2>
- }
-
- The left image would be location <-0.05 1 -3>
- The right image would be location <0.05 1 -3>
-
- A distance of 0.1 apart seems to work well. For lower resolutions, the
- location should never be exactly in-line with the look_at parameter.
-
- The best way to accomplish this is to have a "leftcam.pov" and a
- "rightcam.pov", both of which include a "common.pov" which holds objects
- common to both eyes (generally this is everything except your cameras).
-
- The following is a really nifty demonstration of this effect, and a single
- frame of an animation I am working on.
-
- -source code for TGAMIX.EXE follows:
-
- (Written in Borland C++ 3.1, should work with most other platforms)
-
-
- #include <stdio.h>
- #include <process.h>
- #include <fcntl.h>
- #include <io.h>
-
- typedef unsigned char BYTE;
-
- typedef struct
- {
- BYTE ID;
- BYTE ColorMapType;
- BYTE ImageType;
- unsigned FirstColorMapEntry;
- unsigned ColorMapLength;
- BYTE ColorMapEntrySize;
- unsigned XOrigin;
- unsigned YOrigin;
- unsigned Width;
- unsigned Height;
- BYTE BitsPerPixel;
- BYTE ImageDescriptorBits;
- } imagedata;
-
- typedef struct
- {
- BYTE Blue;
- BYTE Green;
- BYTE Red;
- } RGB24;
-
- void OpenTGAFile(const char *, int *, imagedata *);
- void OpenTargetFile(const char *, int *, imagedata *);
- void ProcessLine(int, int, int, unsigned);
- void ProcessImages(const char *, const char *, const char *);
-
- // open a TGA file, check it's type, return the data.
- // if unable to handle it, or error, exits to OS
- void OpenTGAFile(const char *filename, int *handle, imagedata *data)
- {
- *handle = open(filename, O_RDONLY | O_BINARY);
- if (*handle == -1)
- {
- fprintf(stderr, "\nCannot open %s for reading\n", filename);
- exit(1);
- }
-
- read(*handle, data, sizeof(imagedata));
-
- if (data->ImageType != 2 || data->BitsPerPixel != 24)
- {
- printf("\nImages must be type 2 (true color, uncompressed).\n"
- "(If this is the case, be sure file is 24-bit)\n");
- exit(1);
- }
-
- if (data->Width > 1024)
- {
- printf("\nImages must be no more than 1024 pixels wide.\n");
- exit(1);
- }
- }
-
- // opens the target file, writing data as a header
- void OpenTargetFile(const char *filename, int *handle, imagedata *data)
- {
- *handle = open(filename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC);
- if (*handle == -1)
- {
- fprintf(stderr, "\nCannot open %s for writing\n", filename);
- exit(1);
- }
-
- write(*handle, data, sizeof(imagedata));
- }
-
-
- // reads a line from red and blue, sums the colors, then writes the
- // composite to output
- void ProcessLine(int red, int blue, int output, unsigned width)
- {
- static RGB24 redBuffer[1024];
- static RGB24 blueBuffer[1024];
- static RGB24 outBuffer[1024];
- unsigned i;
-
- read(red, redBuffer, width * sizeof(RGB24));
- read(blue, blueBuffer, width * sizeof(RGB24));
-
- for (i=0; i < width; ++i)
- {
- outBuffer[i].Green = 0;
-
- outBuffer[i].Red = (BYTE)(0.30 * (double)(redBuffer[i].Red) +
- 0.59 * (double)(redBuffer[i].Green) +
- 0.11 * (double)(redBuffer[i].Blue));
-
- outBuffer[i].Blue = (BYTE)(0.30 * (double)(blueBuffer[i].Red) +
- 0.59 * (double)(blueBuffer[i].Green) +
- 0.11 * (double)(blueBuffer[i].Blue));
-
- }
-
- write(output, outBuffer, width * sizeof(RGB24));
- }
-
- // does the whole damn thing
- void ProcessImages(const char *redFile,
- const char *blueFile,
- const char *outFile)
- {
- static imagedata redData;
- static imagedata blueData;
- unsigned width, height, i;
- int redHandle, blueHandle, outHandle;
-
- OpenTGAFile(redFile, &redHandle, &redData);
- OpenTGAFile(blueFile, &blueHandle, &blueData);
-
- if (redData.Width != blueData.Width)
- {
- printf("\nRed and Blue files must be of the same width.\n");
- exit(1);
- }
-
- OpenTargetFile(outFile, &outHandle, &redData);
-
- width = redData.Width;
- height = redData.Height;
-
- for (i = 0; i < height; ++i)
- {
- ProcessLine(redHandle, blueHandle, outHandle, width);
- }
-
- close(redHandle);
- close(blueHandle);
- close(outHandle);
- }
-
-
- void main(int argc, char **argv)
- {
- if (argc < 4)
- {
- printf("\nUsage:\n");
- printf("%s redfile bluefile outfile\n", argv[0]);
- exit(0);
- }
-
- ProcessImages(argv[1], argv[2], argv[3]);
- }
-
- The rest of the files may seem complicated, but this is a frame of an
- animation with common and frame specific objects
-
- -following is leftcam.pov
-
- camera {
- location <-0.05 1 -3>
- direction <0 0 1.5>
- up <0 1 0>
- right <1.33 0 0>
- look_at <0 1 2>
- }
-
- -following is rightcam.pov
-
-
- camera {
- location <0.05 1 -3>
- direction <0 0 1.5>
- up <0 1 0>
- right <1.33 0 0>
- look_at <0 1 2>
- }
-
-
- -following is common.pov
-
-
- #include "colors.inc"
- #include "shapes.inc"
- #include "textures.inc"
-
- object {
- light_source {
- <2 4 -3>
- color
- White
- }
- }
-
- object {
- light_source {
- <-2 4 -3>
- color
- White
- }
- }
-
- object {
- plane {
- <0 1 0> 0
- }
- texture {
- checker
- color White
- color Black
- }
- }
-
- -following is frame1l.pov (frame 1, left image)
-
-
- #include "left.pov"
-
- object {
- sphere {
- <0 1 1> .5
- texture {
- color Grey
- phong 1
- }
- }
- }
-
- object {
- sphere {
- <1.5 1.5 2> .5
- texture {
- color Grey
- phong 1
- }
- }
- }
-
- object {
- sphere {
- <0 2 3> .5
- texture {
- color Grey
- phong 1
- }
- }
- }
-
- object {
- sphere {
- <-1.5 1.5 2> .5
- texture {
- color Grey
- phong 1
- }
- }
- }
-
- -to create frame1r.pov, simply #include "right.pov" instead of "left.pov"
- in the preceeding.
-
- -the following is left.pov
-
-
- #include "common.pov"
- #include "leftcam.pov"
-
- -to create right.pov, simply #include "rightcam.pov" instead of "left.pov"
-
-
- -the following is BUILD.BAT, an MS-DOS batch file to assemble the entire
- mess
-
-
- povray -iframe1l.pov -oleft1.tga
- povray -iframe1r.pov -oright1.tga
- tgamix left1.tga right1.tga data1.tga
- pl286 2gif data1
-
- -and finally, the PicLab script to convert a tga to a gif:
-
- tload %1.tga
- makepal
- map
- gsave %1.gif
-
-
- Please notice there is a minimum of command line options. Read the
- documentation for POVRAY and modify your environment variable or POVRAY.DEF
- file accordingly.
-
- Have fun.
-
- Paul Forgey
- paulf@halcyon.com
-