home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / general / modelers / geomview / source.lha / Geomview / src / lib / mg / gl / mgglshade.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-09-24  |  8.5 KB  |  349 lines

  1. /* Copyright (c) 1992 The Geometry Center; University of Minnesota
  2.    1300 South Second Street;  Minneapolis, MN  55454, USA;
  3.    
  4. This file is part of geomview/OOGL. geomview/OOGL is free software;
  5. you can redistribute it and/or modify it only under the terms given in
  6. the file COPYING, which you should have received along with this file.
  7. This and other related software may be obtained via anonymous ftp from
  8. geom.umn.edu; email: software@geom.umn.edu. */
  9.  
  10. /* Authors: Charlie Gunn, Stuart Levy, Tamara Munzner, Mark Phillips */
  11.  
  12. #include "mgP.h"
  13. #include "mgglP.h"
  14. #include "mgglshade.h"
  15. #include <gl/gl.h>
  16.  
  17. #define MAXDEF 50
  18.  
  19. /* materialno, lightmodelno, and lightno between 1 and 65535 are
  20.  * legal. p 9-9 GL PROG GUIDE (munzner 9/17/91)
  21.  */
  22. static int lightno = 1;
  23. static float kd = 1.0;
  24.  
  25. mggl_appearance( struct mgastk *ma, int mask )
  26. {
  27.   Appearance *ap = &(ma->ap);
  28.  
  29.   if (mask & APF_TRANSP) {
  30.     if (ap->flag & APF_TRANSP) {
  31.       zwritemask(0);
  32.       blendfunction(BF_SA, BF_MSA);
  33.     } else {
  34.       zwritemask(~0);
  35.       blendfunction(BF_ONE, BF_ZERO);
  36.     }
  37.   }
  38.  
  39.   if (mask & APF_LINEWIDTH) {
  40.     linewidth(ap->linewidth);
  41.     _mgc->has &= ~HAS_POINT;
  42.   }
  43.  
  44.   if (mask & APF_SHADING) {
  45.     if(!IS_SHADED(ap->shading) || ma->shader != NULL) {
  46.     /* switch to constant shading by unbinding the lmodel */
  47.     lmbind(LMODEL, 0);
  48.     lmbind(MATERIAL, 0);
  49.     _mgglc->d4f = c4f;
  50.     _mgglc->lmcolor = LMC_COLOR;
  51.     shademodel(IS_SMOOTH(ap->shading) ? GOURAUD : FLAT );
  52.     ma->useshader = (ma->shader != NULL) && IS_SHADED(ap->shading);
  53.     }
  54.     else {
  55.     /* turn shading on */
  56.     shademodel( IS_SMOOTH(ap->shading) ? GOURAUD : FLAT );
  57.     if (ap->lighting->valid)
  58.         lmbind(LMODEL, ma->light_seq);
  59.     lmbind(MATERIAL, ma->mat_seq);
  60.     _mgglc->d4f = mggl_d4f;
  61.     _mgglc->lmcolor = LMC_DIFFUSE;
  62.     ma->useshader = 0;
  63.     }
  64.   }
  65.  
  66.   if(mask & APF_EVERT) {
  67.     /*
  68.      * Do automatic normal-flipping if requested.
  69.      */
  70.     _mgglc->n3f = (ap->flag & APF_EVERT) ?
  71.             (void (*)())mggl_n3fevert : (void (*)())n3f;
  72.   }
  73.  
  74.   /*
  75.    * No GL calls are needed for the following attributes because
  76.    * they are always interpreted at draw-time:
  77.    *        APF_FACEDRAW
  78.    *        APF_EDGEDRAW
  79.    *        APF_NORMSCALE
  80.    */
  81.  
  82. }
  83.  
  84. /*-----------------------------------------------------------------------
  85.  * Function:    mggl_material
  86.  * Description:    bind a material. define it if it's not yet defined.
  87.  * Args:    *mat: Material to bind.
  88.  *        mask: Bitmask telling which material fields are valid.
  89.  *              Passed into mggl_materialdef.
  90.  * Returns:    
  91.  * Author:    munzner
  92.  * Date:    Wed Oct 16 16:06:47 1991
  93.  * Notes:    We must reset the "current GL color" after binding a
  94.  *        material.
  95.  *        We want color calls to change the *diffuse* color when
  96.  *        we're in shading mode. Thus we call lmcolor(LMC_DIFFUSE).
  97.  *        We also must keep track of the diffuse coefficient
  98.  *        for use in mggl_d[3,4]f, our wrapper for color calls.
  99.  *        C3f or c4f should never be called directly.
  100.  *        mg draw routines are responsible for establishing the
  101.  *         correct drawing color.
  102.  */
  103. void
  104. mggl_material(register struct mgastk *astk, int mask)
  105. {
  106.     float surface[MAXDEF];
  107.     register float *f;
  108.     Material *mat = &astk->mat;
  109.     static float lmnull = LMNULL;
  110.  
  111.     mask &= mat->valid;
  112.     if (mask & MTF_Kd)
  113.     kd = mat->kd;
  114.  
  115.     if((mask & (MTF_EMISSION|MTF_DIFFUSE|MTF_AMBIENT|MTF_SPECULAR
  116.         |MTF_SHININESS|MTF_Kd|MTF_Ka|MTF_Ks|MTF_ALPHA)) == 0)
  117.     return;        /* No GL changes to make. */
  118.  
  119.     if(astk->next && astk->next->mat_seq == astk->mat_seq) {
  120.     /*
  121.      * Fresh material needed.  Erase any previous GL definition.
  122.      * We'll need to load all valid fields to initialize it.
  123.      */
  124.     astk->mat_seq++;
  125.     lmdef(DEFMATERIAL, astk->mat_seq, 0, &lmnull);
  126.     lmbind(MATERIAL, astk->mat_seq);
  127.     mask = mat->valid;
  128.     }
  129.  
  130.     /* Build material definition */
  131.     f = surface;
  132.  
  133.     if( mask & MTF_EMISSION) {
  134.     *f++ = EMISSION;
  135.     *f++ = mat->emission.r;
  136.     *f++ = mat->emission.g;
  137.     *f++ = mat->emission.b;
  138.     }
  139.  
  140.     if( mask & (MTF_Ka | MTF_AMBIENT)) {
  141.     *f++ = AMBIENT;
  142.     *f++ = mat->ka * mat->ambient.r;
  143.     *f++ = mat->ka * mat->ambient.g;
  144.     *f++ = mat->ka * mat->ambient.b;
  145.     }
  146.     if( mask & (MTF_Kd | MTF_DIFFUSE)) {
  147.     *f++ = DIFFUSE;
  148.     *f++ = mat->kd * mat->diffuse.r;
  149.     *f++ = mat->kd * mat->diffuse.g;
  150.     *f++ = mat->kd * mat->diffuse.b;
  151.     }
  152.     if( mask & (MTF_Ks | MTF_SPECULAR | MTF_SHININESS)) {
  153.     *f++ = SPECULAR;
  154.     *f++ = mat->ks * mat->specular.r;
  155.     *f++ = mat->ks * mat->specular.g;
  156.     *f++ = mat->ks * mat->specular.b;
  157.     *f++ = SHININESS;
  158.     *f++ = mat->shininess;
  159.     }
  160.     if( mask & MTF_ALPHA) {
  161.     *f++ = ALPHA;
  162.     *f++ = mat->alpha;
  163.     }
  164.  
  165.     *f = LMNULL;
  166.  
  167.     lmdef (DEFMATERIAL, astk->mat_seq, f - surface, surface);
  168. }
  169.  
  170. void
  171. mggl_setshader(mgshadefunc shader)
  172. {
  173.     register struct mgastk *ma = _mgc->astk;
  174.     int wasusing = ma->useshader;
  175.  
  176.     ma->shader = shader;
  177.     ma->useshader = (shader != NULL && IS_SHADED(ma->ap.shading));
  178.     if(ma->useshader != wasusing)
  179.     mggl_appearance(_mgc->astk, APF_SHADING);
  180. }
  181.  
  182. void mggl_lighting(struct mgastk *astk, int mask)
  183. {
  184.   LtLight *light;
  185.   LmLighting *li = &astk->lighting;
  186.  
  187.   if (li->valid) {
  188.     mggl_lightmodeldef( astk->light_seq, li, li->valid & mask );
  189.     lmbind(LMODEL, astk->light_seq);
  190.   }
  191.  
  192.   mmode(MVIEWING);
  193.   pushmatrix();
  194.   loadmatrix( _mgc->W2C );
  195.   mggl_lights( li->lights, astk );
  196.   popmatrix();
  197. }
  198.  
  199. void
  200. mggl_lights( LtLight *light, struct mgastk *astk )
  201. {
  202.   int i, lightsused;
  203.   int baselight = -1;
  204.  
  205.   /* unbind all currently bound GL lights */
  206.   for (i=0; i<MAXLIGHTS; ++i) {
  207.     lmbind(LIGHT0+i, 0);
  208.   }
  209.  
  210.   lightsused = 0;
  211.   while (light) {
  212.     if (light->Private == 0) {
  213.       /* this is a new light */
  214.       if(baselight < 0) {
  215.     register struct mgastk *a;
  216.     for(a = astk, baselight = 1; a != NULL; a = a->next)
  217.         baselight += MAXLIGHTS; /* Count appearance stack depth */
  218.       }
  219.       light->Private = lightsused + baselight;
  220.       light->changed = 1;  /* set changed, to force lmdef below */
  221.     }
  222.  
  223.     if( light->changed ) {
  224.       mggl_lightdef( light->Private, light );
  225.       light->changed = 0;
  226.     }
  227.     lmbind( LIGHT0+lightsused, light->Private );
  228.     ++lightsused;
  229.     light = light->next;
  230.   }
  231. }
  232.  
  233.  
  234. int
  235. mggl_lightdef( int lightno, LtLight *light)
  236. {
  237.     float lightsource[MAXDEF];
  238.     float *f = lightsource;
  239.  
  240.     *f++ = AMBIENT;
  241.     *f++ = light->ambient.r;
  242.     *f++ = light->ambient.g;
  243.     *f++ = light->ambient.b;
  244.  
  245.     *f++ = LCOLOR;
  246.     *f++ = light->intensity * light->color.r;
  247.     *f++ = light->intensity * light->color.g;
  248.     *f++ = light->intensity * light->color.b;
  249.  
  250.     *f++ = POSITION;
  251.     *f++ = light->globalposition.x;
  252.     *f++ = light->globalposition.y;
  253.     *f++ = light->globalposition.z;
  254.     *f++ = light->globalposition.w;
  255.  
  256.     *f++ = LMNULL;
  257.     lmdef( DEFLIGHT, lightno, f-lightsource, lightsource );
  258.     return lightno;
  259. }
  260.  
  261.  
  262. int
  263. mggl_lightmodeldef(int lightmodel, LmLighting *lgt, int mask)
  264. {
  265.     float light[40];
  266.     float *f = light;
  267.  
  268.     if( mask & LMF_AMBIENT) {
  269.     *f++ = AMBIENT;
  270.     *f++ = lgt->ambient.r;
  271.     *f++ = lgt->ambient.g;
  272.     *f++ = lgt->ambient.b;
  273.     }
  274.  
  275.     if( mask & LMF_LOCALVIEWER) {
  276.     *f++ = LOCALVIEWER;
  277.     *f++ = lgt->localviewer;
  278.     }
  279.  
  280.     if( mask & (LMF_ATTENC | LMF_ATTENM)) {
  281.     *f++ = ATTENUATION;
  282.     *f++ = lgt->attenconst;
  283.     *f++ = lgt->attenmult;
  284.     }
  285. #ifdef don_t_do_this
  286.     /* This causes trouble if the vertex order makes GL consider
  287.      * our polygon to be backfacing -- then TWOSIDE causes it
  288.      * to be mis-shaded from both sides..
  289.      */
  290.     if(_mgglc->cantwoside) {
  291.     *f++ = TWOSIDE;        /* Always enable TWOSIDE lighting if hardware */
  292.     *f++ = 1.0;        /* supports it.  (is this a good idea?) */
  293.     }
  294. #endif
  295.  
  296.     *f++ = LMNULL;
  297.     lmdef (DEFLMODEL, lightmodel, f-light, light);
  298.     return lightmodel;
  299. }
  300.  
  301.  
  302. /*-----------------------------------------------------------------------
  303.  * Function:    mggl_d4f
  304.  * Description:    wrapper for c4f
  305.  * Args:    c:
  306.  * Returns:    
  307.  * Author:    munzner
  308.  * Date:    Wed Sep 18 21:48:08 1991
  309.  * Notes:    We must multiply by kd (diffuse coefficient of the material)
  310.  *         since we called lmcolor(LMC_DIFFUSE) earlier in mggl_material
  311.  *         so we're overwriting the diffuse material with every
  312.  *        c4f call.
  313.  */
  314. void
  315. mggl_d4f(c)
  316.     float c[4];
  317. {
  318.     float d[4];
  319.     d[0] = c[0] * kd;
  320.     d[1] = c[1] * kd;
  321.     d[2] = c[2] * kd;
  322.     d[3] = c[3];
  323.     /* Let appearance alpha override object's alpha */
  324.     if (_mgc->astk->mat.valid & MTF_ALPHA &&
  325.     _mgc->astk->mat.override & MTF_ALPHA)
  326.       d[3] = _mgc->astk->mat.alpha;
  327.     c4f(d);
  328. }
  329.  
  330.  
  331. void
  332. mggl_n3fevert(register Point3 *n, register HPoint3 *p)
  333. {
  334.     Point3 tn;
  335.     register Point3 *cp;
  336.  
  337.     if(!(_mgc->has & HAS_CPOS))
  338.     mg_findcam();
  339.     cp = &_mgc->cpos;
  340.     if( (p->x-cp->x) * n->x + (p->y-cp->y) * n->y + (p->z-cp->z) * n->z > 0) {
  341.     tn.x = -n->x;
  342.     tn.y = -n->y;
  343.     tn.z = -n->z;
  344.     n3f((float *)&tn);
  345.     } else {
  346.     n3f((float *)n);
  347.     }
  348. }
  349.