Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. #include "zgl.h"
  2. #include "msghandling.h"
  3.  
  4. void glopMaterial(GLContext *c,GLParam *p)
  5. {
  6.   int mode=p[1].i;
  7.   int type=p[2].i;
  8.   float *v=&p[3].f;
  9.   int i;
  10.   GLMaterial *m;
  11.  
  12.   if (mode == GL_FRONT_AND_BACK) {
  13.     p[1].i=GL_FRONT;
  14.     glopMaterial(c,p);
  15.     mode=GL_BACK;
  16.   }
  17.   if (mode == GL_FRONT) m=&c->materials[0];
  18.   else m=&c->materials[1];
  19.  
  20.   switch(type) {
  21.   case GL_EMISSION:
  22.     for(i=0;i<4;i++)
  23.       m->emission.v[i]=v[i];
  24.     break;
  25.   case GL_AMBIENT:
  26.     for(i=0;i<4;i++)
  27.       m->ambient.v[i]=v[i];
  28.     break;
  29.   case GL_DIFFUSE:
  30.     for(i=0;i<4;i++)
  31.       m->diffuse.v[i]=v[i];
  32.     break;
  33.   case GL_SPECULAR:
  34.     for(i=0;i<4;i++)
  35.       m->specular.v[i]=v[i];
  36.     break;
  37.   case GL_SHININESS:
  38.     m->shininess=v[0];
  39.     m->shininess_i = (v[0]/128.0f)*SPECULAR_BUFFER_RESOLUTION;
  40.     break;
  41.   case GL_AMBIENT_AND_DIFFUSE:
  42.     for(i=0;i<4;i++)
  43.       m->diffuse.v[i]=v[i];
  44.     for(i=0;i<4;i++)
  45.       m->ambient.v[i]=v[i];
  46.     break;
  47.   default:
  48.     assert(0);
  49.   }
  50. }
  51.  
  52. void glopColorMaterial(GLContext *c,GLParam *p)
  53. {
  54.   int mode=p[1].i;
  55.   int type=p[2].i;
  56.  
  57.   c->current_color_material_mode=mode;
  58.   c->current_color_material_type=type;
  59. }
  60.  
  61. void glopLight(GLContext *c,GLParam *p)
  62. {
  63.   int light=p[1].i;
  64.   int type=p[2].i;
  65.   V4 v;
  66.   GLLight *l;
  67.   int i;
  68.  
  69.   assert(light >= GL_LIGHT0 && light < GL_LIGHT0+MAX_LIGHTS );
  70.  
  71.   l=&c->lights[light-GL_LIGHT0];
  72.  
  73.   for(i=0;i<4;i++) v.v[i]=p[3+i].f;
  74.  
  75.   switch(type) {
  76.   case GL_AMBIENT:
  77.     l->ambient=v;
  78.     break;
  79.   case GL_DIFFUSE:
  80.     l->diffuse=v;
  81.     break;
  82.   case GL_SPECULAR:
  83.     l->specular=v;
  84.     break;
  85.   case GL_POSITION:
  86.     {
  87.       V4 pos;
  88.       gl_M4_MulV4(&pos,c->matrix_stack_ptr[0],&v);
  89.  
  90.       l->position=pos;
  91.  
  92.       if (l->position.v[3] == 0) {
  93.         l->norm_position.X=pos.X;
  94.         l->norm_position.Y=pos.Y;
  95.         l->norm_position.Z=pos.Z;
  96.        
  97.         gl_V3_Norm(&l->norm_position);
  98.       }
  99.     }
  100.     break;
  101.   case GL_SPOT_DIRECTION:
  102.     for(i=0;i<3;i++) {
  103.       l->spot_direction.v[i]=v.v[i];
  104.       l->norm_spot_direction.v[i]=v.v[i];
  105.     }
  106.     gl_V3_Norm(&l->norm_spot_direction);
  107.     break;
  108.   case GL_SPOT_EXPONENT:
  109.     l->spot_exponent=v.v[0];
  110.     break;
  111.   case GL_SPOT_CUTOFF:
  112.     {
  113.       float a=v.v[0];
  114.       assert(a == 180 || (a>=0 && a<=90));
  115.       l->spot_cutoff=a;
  116.       if (a != 180) l->cos_spot_cutoff=cos(a * M_PI / 180.0);
  117.     }
  118.     break;
  119.   case GL_CONSTANT_ATTENUATION:
  120.     l->attenuation[0]=v.v[0];
  121.     break;
  122.   case GL_LINEAR_ATTENUATION:
  123.     l->attenuation[1]=v.v[0];
  124.     break;
  125.   case GL_QUADRATIC_ATTENUATION:
  126.     l->attenuation[2]=v.v[0];
  127.     break;
  128.   default:
  129.     assert(0);
  130.   }
  131. }
  132.  
  133.  
  134. void glopLightModel(GLContext *c,GLParam *p)
  135. {
  136.   int pname=p[1].i;
  137.   float *v=&p[2].f;
  138.   int i;
  139.  
  140.   switch(pname) {
  141.   case GL_LIGHT_MODEL_AMBIENT:
  142.     for(i=0;i<4;i++)
  143.       c->ambient_light_model.v[i]=v[i];
  144.     break;
  145.   case GL_LIGHT_MODEL_LOCAL_VIEWER:
  146.     c->local_light_model=(int)v[0];
  147.     break;
  148.   case GL_LIGHT_MODEL_TWO_SIDE:
  149.     c->light_model_two_side = (int)v[0];
  150.     break;
  151.   default:
  152.     tgl_warning("glopLightModel: illegal pname: 0x%x\n", pname);
  153.     //assert(0);
  154.     break;
  155.   }
  156. }
  157.  
  158.  
  159. static inline float clampf(float a,float min,float max)
  160. {
  161.   if (a<min) return min;
  162.   else if (a>max) return max;
  163.   else return a;
  164. }
  165.  
  166. void gl_enable_disable_light(GLContext *c,int light,int v)
  167. {
  168.   GLLight *l=&c->lights[light];
  169.   if (v && !l->enabled) {
  170.     l->enabled=1;
  171.     l->next=c->first_light;
  172.     c->first_light=l;
  173.     l->prev=NULL;
  174.   } else if (!v && l->enabled) {
  175.     l->enabled=0;
  176.     if (l->prev == NULL) c->first_light=l->next;
  177.     else l->prev->next=l->next;
  178.     if (l->next != NULL) l->next->prev=l->prev;
  179.   }
  180. }
  181.  
  182. /* non optimized lightening model */
  183. void gl_shade_vertex(GLContext *c,GLVertex *v)
  184. {
  185.   float R,G,B,A;
  186.   GLMaterial *m;
  187.   GLLight *l;
  188.   V3 n,s,d;
  189.   float dist,tmp,att,dot,dot_spot,dot_spec;
  190.   int twoside = c->light_model_two_side;
  191.  
  192.   m=&c->materials[0];
  193.  
  194.   n.X=v->normal.X;
  195.   n.Y=v->normal.Y;
  196.   n.Z=v->normal.Z;
  197.  
  198.   R=m->emission.v[0]+m->ambient.v[0]*c->ambient_light_model.v[0];
  199.   G=m->emission.v[1]+m->ambient.v[1]*c->ambient_light_model.v[1];
  200.   B=m->emission.v[2]+m->ambient.v[2]*c->ambient_light_model.v[2];
  201.   A=clampf(m->diffuse.v[3],0,1);
  202.  
  203.   for(l=c->first_light;l!=NULL;l=l->next) {
  204.     float lR,lB,lG;
  205.    
  206.     /* ambient */
  207.     lR=l->ambient.v[0] * m->ambient.v[0];
  208.     lG=l->ambient.v[1] * m->ambient.v[1];
  209.     lB=l->ambient.v[2] * m->ambient.v[2];
  210.  
  211.     if (l->position.v[3] == 0) {
  212.       /* light at infinity */
  213.       d.X=l->position.v[0];
  214.       d.Y=l->position.v[1];
  215.       d.Z=l->position.v[2];
  216.       att=1;
  217.     } else {
  218.       /* distance attenuation */
  219.       d.X=l->position.v[0]-v->ec.v[0];
  220.       d.Y=l->position.v[1]-v->ec.v[1];
  221.       d.Z=l->position.v[2]-v->ec.v[2];
  222.       dist=sqrt(d.X*d.X+d.Y*d.Y+d.Z*d.Z);
  223.       if (dist>1E-3) {
  224.         tmp=1/dist;
  225.         d.X*=tmp;
  226.         d.Y*=tmp;
  227.         d.Z*=tmp;
  228.       }
  229.       att=1.0f/(l->attenuation[0]+dist*(l->attenuation[1]+
  230.                                      dist*l->attenuation[2]));
  231.     }
  232.     dot=d.X*n.X+d.Y*n.Y+d.Z*n.Z;
  233.     if (twoside && dot < 0) dot = -dot;
  234.     if (dot>0) {
  235.       /* diffuse light */
  236.       lR+=dot * l->diffuse.v[0] * m->diffuse.v[0];
  237.       lG+=dot * l->diffuse.v[1] * m->diffuse.v[1];
  238.       lB+=dot * l->diffuse.v[2] * m->diffuse.v[2];
  239.  
  240.       /* spot light */
  241.       if (l->spot_cutoff != 180) {
  242.         dot_spot=-(d.X*l->norm_spot_direction.v[0]+
  243.                    d.Y*l->norm_spot_direction.v[1]+
  244.                    d.Z*l->norm_spot_direction.v[2]);
  245.         if (twoside && dot_spot < 0) dot_spot = -dot_spot;
  246.         if (dot_spot < l->cos_spot_cutoff) {
  247.           /* no contribution */
  248.           continue;
  249.         } else {
  250.           /* TODO: optimize */
  251.           if (l->spot_exponent > 0) {
  252.             att=att*pow(dot_spot,l->spot_exponent);
  253.           }
  254.         }
  255.       }
  256.  
  257.       /* specular light */
  258.      
  259.       if (c->local_light_model) {
  260.         V3 vcoord;
  261.         vcoord.X=v->ec.X;
  262.         vcoord.Y=v->ec.Y;
  263.         vcoord.Z=v->ec.Z;
  264.         gl_V3_Norm(&vcoord);
  265.         s.X=d.X-vcoord.X;
  266.         s.Y=d.Y-vcoord.X;
  267.         s.Z=d.Z-vcoord.X;
  268.       } else {
  269.         s.X=d.X;
  270.         s.Y=d.Y;
  271.         s.Z=d.Z+1.0;
  272.       }
  273.       dot_spec=n.X*s.X+n.Y*s.Y+n.Z*s.Z;
  274.       if (twoside && dot_spec < 0) dot_spec = -dot_spec;
  275.       if (dot_spec>0) {
  276.         GLSpecBuf *specbuf;
  277.         int idx;
  278.         tmp=sqrt(s.X*s.X+s.Y*s.Y+s.Z*s.Z);
  279.         if (tmp > 1E-3) {
  280.           dot_spec=dot_spec / tmp;
  281.         }
  282.      
  283.         /* TODO: optimize */
  284.         /* testing specular buffer code */
  285.         /* dot_spec= pow(dot_spec,m->shininess);*/
  286.         specbuf = specbuf_get_buffer(c, m->shininess_i, m->shininess);
  287.         idx = (int)(dot_spec*SPECULAR_BUFFER_SIZE);
  288.         if (idx > SPECULAR_BUFFER_SIZE) idx = SPECULAR_BUFFER_SIZE;
  289.         dot_spec = specbuf->buf[idx];
  290.         lR+=dot_spec * l->specular.v[0] * m->specular.v[0];
  291.         lG+=dot_spec * l->specular.v[1] * m->specular.v[1];
  292.         lB+=dot_spec * l->specular.v[2] * m->specular.v[2];
  293.       }
  294.     }
  295.  
  296.     R+=att * lR;
  297.     G+=att * lG;
  298.     B+=att * lB;
  299.   }
  300.  
  301.   v->color.v[0]=clampf(R,0,1);
  302.   v->color.v[1]=clampf(G,0,1);
  303.   v->color.v[2]=clampf(B,0,1);
  304.   v->color.v[3]=A;
  305. }
  306.  
  307.