home *** CD-ROM | disk | FTP | other *** search
/ Virtual Reality Homebrewer's Handbook / vr.iso / vr386 / colormap.c < prev    next >
C/C++ Source or Header  |  1996-03-19  |  9KB  |  293 lines

  1. /* Routine to setup and compute colors */
  2. /* for 256-color mode                */
  3.  
  4. /* Written by Dave Stampe Mar 21 1992 */
  5. /* Completely rewritten for VR-386 by Dave Stampe, Dec. 1993 */
  6.  
  7. // The idea of this code is to let you change the way lighting
  8. // maps polygon attributes to color values that user_render_poly
  9. // recieves, to allow for new effects.
  10.  
  11. // VR-386 also allows flexible handling of new LIGHT structures
  12.  
  13.  
  14. /*
  15.  This code is part of the VR-386 project, created by Dave Stampe.
  16.  VR-386 is a desendent of REND386, created by Dave Stampe and
  17.  Bernie Roehl.  Almost all the code has been rewritten by Dave
  18.  Stampre for VR-386.
  19.  
  20.  Copyright (c) 1994 by Dave Stampe:
  21.  May be freely used to write software for release into the public domain
  22.  or for educational use; all commercial endeavours MUST contact Dave Stampe
  23.  (dstampe@psych.toronto.edu) for permission to incorporate any part of
  24.  this software or source code into their products!  Usually there is no
  25.  charge for under 50-100 items for low-cost or shareware products, and terms
  26.  are reasonable.  Any royalties are used for development, so equipment is
  27.  often acceptable payment.
  28.  
  29.  ATTRIBUTION:  If you use any part of this source code or the libraries
  30.  in your projects, you must give attribution to VR-386 and Dave Stampe,
  31.  and any other authors in your documentation, source code, and at startup
  32.  of your program.  Let's keep the freeware ball rolling!
  33.  
  34.  DEVELOPMENT: VR-386 is a effort to develop the process started by
  35.  REND386, improving programmer access by rewriting the code and supplying
  36.  a standard API.  If you write improvements, add new functions rather
  37.  than rewriting current functions.  This will make it possible to
  38.  include you improved code in the next API release.  YOU can help advance
  39.  VR-386.  Comments on the API are welcome.
  40.  
  41.  CONTACT: dstampe@psych.toronto.edu
  42. */
  43.  
  44.  
  45. #include <stdio.h>
  46. #include <stdlib.h>  /* strtoul() */
  47. #include <dos.h>
  48. #include <ctype.h>   /* isdigit(), isalnum() */
  49. #include <string.h>  /* strnicmp() */
  50.  
  51. #include "vr_api.h"
  52. #include "intmath.h"
  53. #include "renderer.h"
  54.  
  55. //*********************************************************/
  56. /* USER POLYGON LIGHTING ROUTINE: DETERMINES POLY COLOR # */
  57.  
  58. /* The 16-bit color the user specifies for a polygon is broken down as
  59.    follows:
  60.          H R SS CCCC BBBBBBBB
  61.  
  62.    H is the highlight flag (the polygon should be highlighted in
  63.    some way, usually by outlining it in the highlight_color given above).
  64.  
  65.    R is a reserved bit, which should be set to zero
  66.  
  67.    SS is a two-bit field specifying one of four surface types:
  68.  
  69.       00 is a constant-color surface; the 4-bit field CCCC is ignored, and the
  70.      8-bit field BBBBBBBB is used as an absolute color number
  71.  
  72.       01 is a cosine-lit surface; the 4-bit field CCCC specifies one of 16
  73.      basic colors, and the 8-bit brightness field BBBBBBBB is multiplied
  74.      by the cosine of the angle between the light source and the polygon's
  75.      surface normal to provide a 4-bit shading value.
  76.  
  77.       10 is a pseudo-metallic surface; the CCCC field gives the starting hue,
  78.      and the BBBBBBBB value is ignored.  The color will cycle through
  79.      the different shades to give a 'metallic' effect.
  80.  
  81.       11 is a pseudo-transparent surface made up of alternating rows of
  82.      spaced dots; other than that, it behaves like a pseudo-metallic
  83.      surface.
  84.  
  85.    This routine maps the above into an 8-bit color number in the low byte
  86.    of its return value, and passes through the top four bits.
  87.  
  88.  */
  89.  
  90.  
  91.  
  92.  /// NOTE FOR MULTIPLE LIGHT IMPLEMENTATION:
  93.  /// MAKE SUM OF AMBIENT AND OTHER LIGHTS 127
  94.  /// TO PREVENT SATURATION.  SUM ALL COSINE-LIT
  95.  /// LIGHTS AS SEEN BELOW:
  96.  
  97.  
  98. //*********** EXTERNAL LIGHTING CONTROL *************
  99.  
  100. static WORD ambient_light = 76;
  101.  
  102. static WORD light1_i = 51;
  103. static COORD light1_x = 1000, light1_y = 15000, light1_z = -5000;
  104. static BOOL light1_s = 0;
  105.  
  106. static WORD light2_i = 0;
  107. static COORD light2_x, light2_y, light2_z;
  108. static BOOL light2_s = 0;
  109.  
  110.  
  111.     // in COLORMAP.C, sets up lights to renderer
  112.     // this version takes only 3: plus sum of ambient
  113. void setup_lights(LIGHT *llist[3], WORD nlights)
  114. {
  115.   int i,j,k;
  116.   LIGHT *l;
  117.   COORD x,y,z;
  118.   DWORD lsum = 0;
  119.   DWORD isum = 0;
  120.   DWORD totlights = 0;
  121.  
  122.   for(i=0;i<nlights;i++)
  123.     {
  124.       l = llist[i];
  125.       if(get_light_intensity(l)==0) continue;
  126.       if(get_light_type(l)==AMBIENT_LIGHT) isum += get_light_intensity(l);
  127.       else if(totlights==0)
  128.     {
  129.      light1_s = get_light_data(l, &light1_x,&light1_y,&light1_z,&light1_i);
  130.      lsum += light1_i;
  131.      totlights++;
  132.     }
  133.       else if(totlights==1)
  134.     {
  135.      light2_s = get_light_data(l, &light2_x,&light2_y,&light2_z,&light2_i);
  136.      lsum += light2_i;
  137.      totlights++;
  138.     }
  139.     }
  140.  
  141.   lsum += isum;
  142.   ambient_light = mulmuldiv(isum,127,lsum);    // scale lights so sum is 127
  143.   light1_i = mulmuldiv(light1_i, 127,lsum);
  144.   light2_i = mulmuldiv(light2_i, 127,lsum);
  145.   light1_s = (light1_s == SPOT_LIGHT);
  146.   light2_s = (light2_s == SPOT_LIGHT);
  147.  }
  148.  
  149.  
  150. //*************** SPECIFIC POLY LIGHTING/COLORING ***********
  151.  
  152. static WORD map_mono16(POLY *p, int pcolor, int n)
  153.  {
  154.   int hilite = pcolor & 0xF000;     /* highlight flag (MSB) */
  155.   int bright = pcolor & 0xFF;         /* albedo     */
  156.   int hue = (pcolor & 0x0F00) >> 8;     /* basis color     */
  157.   int color;
  158.   unsigned light;
  159.  
  160.   if (hue == 0)
  161.      return ((bright & 15) | hilite); /* abs. palette color */
  162.  
  163.   if ((pcolor & 0x3000) == 0 || n<3)
  164.     {
  165.       if (bright > 15) bright = 15;  /* fixed (unlit) color or line */
  166.       return (hilite | bright);      /* compute from hue, bright */
  167.     }
  168.  
  169.   if (pcolor & 0x2000) /* metal/glass cycle phase compute */
  170.     {
  171.       color = compute_poly_cosine(p, light1_x, light1_y, light1_z, 0);
  172.  
  173.       color = (bright >> 6) - (color >> 5) + ((hue+320) >> 6);
  174.       if (color < 0) color = 0;
  175.       if (color > 15) color = 15;
  176.       return (hilite | color);
  177.     }
  178.             /* COSINE-LIT COLOR */
  179.   light = 0;
  180.   if(light1_i)
  181.     {
  182.       color = compute_poly_cosine(p, light1_x, light1_y, light1_z, light1_s);
  183.       if (color > 0)
  184.     light += color*light1_i;
  185.     }
  186.   if (light2_i)
  187.     {
  188.       color = compute_poly_cosine(p, light2_x, light2_y, light2_z, light2_s);
  189.       if (color > 0)
  190.     light += color*light2_i;
  191.     }
  192.  
  193.     // this is laboriously hand-tweeked for best range!
  194.  
  195.  color = (light>>7) + ambient_light;     // 0 to 127 total
  196.  color = (color * (bright>>1))>>5;       // 0 to 511
  197.  color = (hue+16) * color;
  198.  color = color>>10;
  199.  
  200.  if (color <= 0) return( hilite );
  201.  if (color > 15) return (15 | hilite);
  202.  return (color | hilite);
  203. }
  204.  
  205.  
  206. static WORD map_color256(POLY *p, int pcolor, int n)
  207.  {
  208.   int hilite = pcolor & 0xF000;     /* highlight flag (MSB) */
  209.   int bright = pcolor & 0xFF;         /* albedo     */
  210.   int hue = (pcolor & 0x0F00) >> 4;     /* basis color     */
  211.   int color;
  212.   unsigned light;
  213.  
  214.   if ((pcolor & 0x3000) == 0 || n<3)
  215.    {                    /* fixed (unlit) color or not poly */
  216.      if (hue==0) return bright | hilite;            /* black */
  217.      return hilite | hue | ((bright >> 4) & 0x0F) ;
  218.    }
  219.  
  220.   if (pcolor & 0x2000)     /* metal/glass cycle phase */
  221.    {
  222.      color = compute_poly_cosine(p, light1_x, light1_y, light1_z, 0);
  223.  
  224.      color = (bright-(color<<1))>>4;                       /* cycle phase */
  225.      return hilite | hue | ((color<<4)&256) | (color&15); /* encode phase */
  226.    }
  227.                 /** COSINE-LIT COLOR **/
  228.   light = 0;
  229.   if(light1_i)
  230.     {
  231.       color = compute_poly_cosine(p, light1_x, light1_y, light1_z, light1_s);
  232.       if (color > 0)
  233.     light += color*light1_i;
  234.     }
  235.   if (light2_i)
  236.     {
  237.       color = compute_poly_cosine(p, light2_x, light2_y, light2_z, light2_s);
  238.       if (color > 0)
  239.     light += color*light2_i;
  240.     }
  241.  
  242.   color = (((light>>7) + ambient_light)*bright)>>11;
  243.   if (color < 1) return hilite;        /* absolute zero: black */
  244.  
  245.   if (color > 15) return (15 | hue | hilite);  /* clip brite */
  246.   return (color | hue | hilite);
  247. }
  248.  
  249.  
  250.  
  251. unsigned user_poly_color(POLY *p, unsigned pcolor, unsigned npoints, long maxz)
  252. {
  253.   switch(screeninfo->colors)
  254.     {
  255.       case 16:
  256.     return map_mono16(p, pcolor, npoints);
  257.       case 256:
  258.     return map_color256(p, pcolor, npoints);
  259.       default:
  260.     return pcolor;   /* unknown color mapping type */
  261.     }
  262. }
  263.  
  264.  
  265.  
  266. //*****************************************************
  267. //** MAP ASCII TO COLOR CODE
  268.  
  269. WORD convert_color(char *s, char **ptr)
  270. {
  271.   int hue, value;
  272.  
  273.   if (isdigit(*s)) return (unsigned) strtoul(s, ptr, 0);
  274.   if (ptr) for (*ptr = s; isalnum(**ptr) || **ptr == '_'; ++*ptr);
  275.   if (!strnicmp(s, "shaded", 6))
  276.     {
  277.       sscanf(s, "shaded_%d_%d", &hue, &value);
  278.       return 0x1000 | ((hue & 0x0F) << 8) | (value & 0xFF);
  279.     }
  280.   else if (!strnicmp(s, "metal", 5))
  281.     {
  282.       sscanf(s, "metal_%d_%d", &hue, &value);
  283.       return 0x2000 | ((hue & 0x0F) << 8) | ((value & 0x1F) << 3);
  284.     }
  285.   else if (!strnicmp(s, "glass", 5))
  286.     {
  287.       sscanf(s, "glass_%d_%d", &hue, &value);
  288.       return 0x3000 | ((hue & 0x0F) << 8) | ((value & 0x1F) << 3);
  289.     }
  290.   return 0;
  291. }
  292.  
  293.