home *** CD-ROM | disk | FTP | other *** search
/ Enter 2005 March / ENTER.ISO / files / fwp-0.0.6-win32-installer.exe / Shader.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-12-06  |  20.3 KB  |  796 lines

  1. #include "Shader.h"
  2.  
  3. #include "RendererInfo.h"
  4. #include "Renderer.h"
  5. #include "TextureHandler.h"
  6. #include "log.h"
  7.  
  8. #include <stdlib.h>
  9.  
  10. AnimFunction::AnimFunction(int numSamples, char** samples){
  11.     this->numSamples=numSamples<SHADER_ANIM_FUNCTION_MAX_SAMPLES ? numSamples : SHADER_ANIM_FUNCTION_MAX_SAMPLES;
  12.     for(int i=0;i<this->numSamples;i++){
  13.         sscanf(samples[i], "%i %f", &this->samples[i].time, &this->samples[i].value);
  14.     //    printf("sample: %i, %f  ; numSamples: %i\n", this->samples[i].time, this->samples[i].value, this->numSamples);
  15.     }
  16. }
  17. AnimFunction::~AnimFunction(){
  18. }
  19. float AnimFunction::getValue(int time){
  20.     int sample;
  21.  
  22.     for(sample=0;sample<numSamples-1;sample++){
  23.         if(time>=samples[sample].time && time<samples[sample+1].time)
  24.             break;
  25.     }
  26.     if(sample>=numSamples-1)
  27.         return 0.0f;
  28.  
  29.     float t=(time-samples[sample].time)/(float)(samples[sample+1].time-samples[sample].time);
  30.  
  31.     return (t*samples[sample+1].value + (1.0f-t)*samples[sample].value);
  32. }
  33.  
  34.  
  35. ColAnim::ColAnim(){
  36.     red=NULL;
  37.     green=NULL;
  38.     blue=NULL;
  39.     alpha=NULL;
  40.     duration=0;
  41.     combineMode=SHADER_COMBINE_MODE_ADD;
  42. }
  43. ColAnim::~ColAnim(){
  44.     if(red!=NULL)
  45.         delete red;
  46.     if(green!=NULL)
  47.         delete green;
  48.     if(blue!=NULL)
  49.         delete blue;
  50.     if(alpha!=NULL)
  51.         delete alpha;
  52. }
  53. void ColAnim::setup(unsigned int time){
  54.     if(duration==0)
  55.         return;
  56.  
  57.     vec4_t col;
  58.     int modTime=time % duration;
  59.     float r=0.0f;
  60.     float g=0.0f;
  61.     float b=0.0f;
  62.     float a=0.0f;
  63.  
  64.     if(red!=NULL)
  65.         r=red->getValue(modTime);
  66.     if(green!=NULL)
  67.         g=green->getValue(modTime);
  68.     if(blue!=NULL)
  69.         b=blue->getValue(modTime);
  70.     if(alpha!=NULL)
  71.         a=alpha->getValue(modTime);
  72.  
  73.     vectorInit4d(r, g, b, a, col);
  74.     if(combineMode==SHADER_COMBINE_MODE_ADD){
  75.         // get glcolor;
  76.         // add...
  77.     }else if(combineMode==SHADER_COMBINE_MODE_MODULATE){
  78.         // get glcolor;
  79.         // add...
  80.     }else if(combineMode==SHADER_COMBINE_MODE_REPLACE){
  81.         glColor4fv(col);
  82.     }
  83. }
  84. void ColAnim::setdown(){
  85. }
  86. bool ColAnim::readFromFile(File* f){
  87.     char buff[256];
  88.     Tokenizer t(" =\t\n\r\"", "\"");
  89.  
  90.     while(f->readLine(256, buff, true) != -1){
  91.         //printf("COLANIM: line: %s\n", buff);
  92.         t.tokenize(buff);
  93.  
  94.         if(t.tokc==0)
  95.             continue;
  96. /*
  97.         if(t.tokc!=2){
  98.             warn("(in Arena::readFromFile()): Wrong number of tokens in line %i (needed 2 but read %i).\n\n", line, t.tokc);
  99.             continue;
  100.         }
  101. */
  102.         if(streq(t.tokv[0], "red") && t.tokc>1){
  103.             red=new AnimFunction(t.tokc-1, &t.tokv[1]);
  104.             if(red->samples[red->numSamples-1].time > duration)
  105.                 duration=red->samples[red->numSamples-1].time;
  106.         }else if(streq(t.tokv[0], "green") && t.tokc>1){
  107.             green=new AnimFunction(t.tokc-1, &t.tokv[1]);
  108.             if(green->samples[green->numSamples-1].time > duration)
  109.                 duration=green->samples[green->numSamples-1].time;
  110.         }else if(streq(t.tokv[0], "blue") && t.tokc>1){
  111.             blue=new AnimFunction(t.tokc-1, &t.tokv[1]);
  112.             if(blue->samples[blue->numSamples-1].time > duration)
  113.                 duration=blue->samples[blue->numSamples-1].time;
  114.         }else if(streq(t.tokv[0], "alpha") && t.tokc>1){
  115.             alpha=new AnimFunction(t.tokc-1, &t.tokv[1]);
  116.             if(alpha->samples[alpha->numSamples-1].time > duration)
  117.                 duration=alpha->samples[alpha->numSamples-1].time;
  118.         }else if(streq(t.tokv[0], "combineMode")){
  119.             if(streq(t.tokv[1], "ADD")){
  120.                 combineMode=SHADER_COMBINE_MODE_ADD;
  121.             }else if(streq(t.tokv[1], "MODULATE")){
  122.                 combineMode=SHADER_COMBINE_MODE_MODULATE;
  123.             }else if(streq(t.tokv[1], "REPLACE")){
  124.                 combineMode=SHADER_COMBINE_MODE_REPLACE;
  125.             }else{
  126.                 warn("(in TexCoordAnim::readFromFile() (%s, line %i)): Unknown combineMode '%s'.\n\n", f->filename, f->line, t.tokv[1]);
  127.             }
  128.  
  129.         }else if(streq(t.tokv[0], "{")){
  130.             continue;
  131.         }else if(streq(t.tokv[0], "}")){
  132.             break;//return true;
  133.         }else{
  134.             warn("(in TexCoordAnim::readFromFile() (%s, line %i)): Unknown token '%s'.\n\n", f->filename, f->line, t.tokv[0]);
  135.         }
  136.     }
  137.  
  138.     return true;
  139. }
  140.  
  141.  
  142. BaseOptions::BaseOptions(){
  143.     flags=0;
  144.     collisionFlags=COLLISION_FLAG_NONE;
  145.     surfaceType = MATERIAL_SURFACE_TYPE_METAL;
  146.     vectorInit4d(1.0f, 1.0f, 1.0f, 1.0f, color);
  147.     colAnim=NULL;
  148.     alphaFunc_id=0;    // oder GL_GREATER??
  149.     alphaFunc_val=0.0f;
  150.     depthFunc_id=0;
  151.     depthFunc_val=0.0f;
  152.     blendFunc_srcFactor=GL_SRC_ALPHA;
  153.     blendFunc_dstFactor=GL_ONE_MINUS_SRC_ALPHA;
  154.     polygonOffset = 0.0f;
  155. }
  156.  
  157. BaseOptions::~BaseOptions(){
  158.     if(colAnim!=NULL)
  159.         delete colAnim;
  160. }
  161.  
  162.  
  163. void BaseOptions::setup(unsigned int time){
  164.     glColor4fv(color);
  165.  
  166.     if(flags & SHADER_FLAG_BLEND){
  167.         glEnable(GL_BLEND);
  168.         glBlendFunc(blendFunc_srcFactor, blendFunc_dstFactor);
  169.     }
  170.     if(flags & SHADER_FLAG_ALPHA_TEST){
  171.         glAlphaFunc(alphaFunc_id, alphaFunc_val);
  172.         glEnable(GL_ALPHA_TEST);
  173.     }
  174.     if(flags & SHADER_FLAG_NO_LIGHTING){
  175.         Renderer::disableLighting();
  176.     }
  177. //    if(flags & SHADER_FLAG_NO_DEPTH_WRITE){
  178. //        glDisable(GL_DEPTH_WRITE);
  179. //    }
  180.     if(flags & SHADER_FLAG_TWO_SIDED){
  181.         glDisable(GL_CULL_FACE);
  182.     }
  183.  
  184.     if(flags & SHADER_FLAG_POLYGON_OFFSET){
  185.         glEnable(GL_POLYGON_OFFSET_FILL);
  186.         glPolygonOffset(polygonOffset, polygonOffset);
  187.     }
  188.  
  189.     if(colAnim!=NULL){
  190.         colAnim->setup(time);
  191.     }
  192. }
  193.  
  194. void BaseOptions::setdown(){
  195.  
  196.     if(flags & SHADER_FLAG_BLEND){
  197.         glDisable(GL_BLEND);
  198.     }
  199.     if(flags & SHADER_FLAG_ALPHA_TEST){
  200.         glDisable(GL_ALPHA_TEST);
  201.     }
  202.     if(flags & SHADER_FLAG_NO_LIGHTING){
  203.         Renderer::enableLighting();
  204.     }
  205. //    if(flags & SHADER_FLAG_NO_DEPTH_WRITE){
  206. //        glEnable(GL_DEPTH_WRITE);
  207. //    }
  208.     if(flags & SHADER_FLAG_TWO_SIDED){
  209.         glEnable(GL_CULL_FACE);
  210.     }
  211.  
  212.     if(flags & SHADER_FLAG_POLYGON_OFFSET){
  213.         glDisable(GL_POLYGON_OFFSET_FILL);
  214.     }
  215.  
  216.     if(colAnim!=NULL){
  217.         colAnim->setdown();
  218.     }
  219. }
  220.  
  221. bool BaseOptions::readFromFile(File* f){
  222.     char buff[256];
  223.     Tokenizer t(" =\t\n\r\"|", "\"");
  224.  
  225.     while(f->readLine(256, buff, true) != -1){
  226.         //printf("BASE: line: %s\n", buff);
  227.         t.tokenize(buff);
  228.  
  229.         if(t.tokc==0)
  230.             continue;
  231. /*
  232.         if(t.tokc!=2){
  233.             warn("(in Arena::readFromFile()): Wrong number of tokens in line %i (needed 2 but read %i).\n\n", line, t.tokc);
  234.             continue;
  235.         }
  236. */
  237.         if(streq(t.tokv[0], "flags")){
  238.             for(int i=1;i<t.tokc;i++){
  239.                 if(streq(t.tokv[i], "BLEND")){
  240.                     flags |= SHADER_FLAG_BLEND;
  241.                 }else if(streq(t.tokv[i], "ALPHA_TEST")){
  242.                     flags |= SHADER_FLAG_ALPHA_TEST;
  243.                 }else if(streq(t.tokv[i], "NO_DEPTH_TEST")){
  244.                     flags |= SHADER_FLAG_NO_DEPTH_TEST;
  245.                 }else if(streq(t.tokv[i], "NO_DEPTH_WRITE")){
  246.                     flags |= SHADER_FLAG_NO_DEPTH_WRITE;
  247.                 }else if(streq(t.tokv[i], "NO_LIGHTING")){
  248.                     flags |= SHADER_FLAG_NO_LIGHTING;
  249.                 }else if(streq(t.tokv[i], "TWO_SIDED")){
  250.                     flags |= SHADER_FLAG_TWO_SIDED;
  251.                 }else if(streq(t.tokv[i], "POLYGON_OFFSET")){
  252.                     flags |= SHADER_FLAG_POLYGON_OFFSET;
  253.                 }else{
  254.                     warn("(in BaseOptions::readFromFile() (%s, line %i)): Unknown flag '%s'.\n\n", f->filename, f->line, t.tokv[i]);
  255.                 }
  256.  
  257.             }
  258.         }else if(streq(t.tokv[0], "collisionFlags")){
  259.             for(int i=1;i<t.tokc;i++){
  260.                 if(streq(t.tokv[i], "WALK_THROUGH")){
  261.                     collisionFlags |= COLLISION_FLAG_WALK_THROUGH;
  262.                 }else if(streq(t.tokv[i], "SHOOT_THROUGH")){
  263.                     collisionFlags |= COLLISION_FLAG_SHOOT_THROUGH;
  264.                 }else{
  265.                     warn("(in BaseOptions::readFromFile() (%s, line %i)): Unknown collisionFlag '%s'.\n\n", f->filename, f->line, t.tokv[i]);
  266.                 }
  267.  
  268.             }
  269.         }else if(streq(t.tokv[0], "blendFunc") && t.tokc==3){
  270.             if(streq(t.tokv[1], "SRC_ALPHA")){
  271.                 blendFunc_srcFactor=GL_SRC_ALPHA;
  272.             }else if(streq(t.tokv[1], "ONE_MINUS_SRC_ALPHA")){
  273.                 blendFunc_srcFactor=GL_ONE_MINUS_SRC_ALPHA;
  274.             }else{
  275.                 warn("(in BaseOptions::readFromFile() (%s, line %i)): Unknown source blend factor '%s'.\n\n", f->filename, f->line, t.tokv[1]);
  276.             }
  277.  
  278.             if(streq(t.tokv[2], "SRC_ALPHA")){
  279.                 blendFunc_dstFactor=GL_SRC_ALPHA;
  280.             }else if(streq(t.tokv[2], "ONE_MINUS_SRC_ALPHA")){
  281.                 blendFunc_dstFactor=GL_ONE_MINUS_SRC_ALPHA;
  282.             }else{
  283.                 warn("(in BaseOptions::readFromFile() (%s, line %i)): Unknown destination blend factor '%s'.\n\n", f->filename, f->line, t.tokv[2]);
  284.             }
  285.         }else if(streq(t.tokv[0], "alphaFunc") && t.tokc==3){
  286.             if(streq(t.tokv[1], "NEVER")){
  287.                 alphaFunc_id=GL_NEVER;
  288.             }else if(streq(t.tokv[1], "ALWAYS")){
  289.                 alphaFunc_id=GL_ALWAYS;
  290.             }else if(streq(t.tokv[1], "GREATER")){
  291.                 alphaFunc_id=GL_GREATER;
  292.             }else if(streq(t.tokv[1], "LESS")){
  293.                 alphaFunc_id=GL_LESS;
  294.             }else if(streq(t.tokv[1], "EQUAL")){
  295.                 alphaFunc_id=GL_EQUAL;
  296.             }else if(streq(t.tokv[1], "NOTEQUAL")){
  297.                 alphaFunc_id=GL_NOTEQUAL;
  298.             }else{
  299.                 warn("(in BaseOptions::readFromFile() (%s, line %i)): Unknown alphaFunc id '%s'.\n\n", f->filename, f->line, t.tokv[1]);
  300.             }
  301.  
  302.             alphaFunc_val=(float)atof(t.tokv[2]);
  303.         }else if(streq(t.tokv[0], "polygonOffset") && t.tokc==2){
  304.             polygonOffset = (float)atof(t.tokv[1]);
  305.         }else if(streq(t.tokv[0], "color")){
  306.             sscanf(t.tokv[1], "%f %f %f %f", &color[0], &color[1], &color[2], &color[3]);
  307.         }else if(streq(t.tokv[0], "colAnim")){
  308.             colAnim=new ColAnim();
  309.             colAnim->readFromFile(f);
  310.  
  311.         }else if(streq(t.tokv[0], "{")){
  312.             continue;
  313.         }else if(streq(t.tokv[0], "}")){
  314.             break;//return true;
  315.         }else{
  316.             warn("(in BaseOptions::readFromFile() (%s, line %i)): Unknown token '%s'.\n\n", f->filename, f->line, t.tokv[0]);
  317.         }
  318.     }
  319.  
  320.     return true;
  321. }
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328. TexAnim::TexAnim(){
  329.     numFrames=0;
  330.     duration=0;
  331. }
  332.  
  333. TexAnim::~TexAnim(){
  334.     for(int i=0;i<numFrames;i++){
  335.         TextureHandler::releaseTexture(frames[i].texture);
  336.     }
  337. }
  338.  
  339. void TexAnim::setup(unsigned int time){
  340.     if(duration==0)
  341.         return;
  342.  
  343.     int frame=0;
  344.     int modTime=time % duration;
  345.  
  346.     for(frame=0;frame<numFrames;frame++){
  347.         if(modTime>=frames[frame].startTime && modTime<frames[frame].startTime+frames[frame].delayTime)
  348.             break;
  349.     }
  350.     if(frame<numFrames){
  351.         glBindTexture(GL_TEXTURE_2D, frames[frame].texture->texName);
  352.     }
  353. }
  354.  
  355. void TexAnim::setdown(){
  356. }
  357.  
  358. bool TexAnim::readFromFile(File* f){
  359.     char buff[256];
  360.     Tokenizer t(" =\t\n\r\"|", "\"");
  361.  
  362.     while(f->readLine(256, buff, true) != -1){
  363.         //printf("TEXANIM: line: %s\n", buff);
  364.         t.tokenize(buff);
  365.  
  366.         if(t.tokc==0)
  367.             continue;
  368. /*
  369.         if(t.tokc!=2){
  370.             warn("(in TexAnim::readFromFile()): Wrong number of tokens (needed 2 but read %i).\n\n", t.tokc);
  371.             continue;
  372.         }
  373. */
  374.         if(streq(t.tokv[0], "{")){
  375.             continue;
  376.         }else if(streq(t.tokv[0], "}")){
  377.             break;//return true;
  378.         }else if(t.tokc==2){
  379.             Tokenizer t2(t.tokv[0], "[]", "");
  380.             if(t2.tokc==3)
  381.                 readRange(&t2, atoi(t.tokv[1]));
  382.             else{
  383.                 frames[numFrames].texture=TextureHandler::getTexture(t.tokv[0]);
  384.                 frames[numFrames].delayTime=atoi(t.tokv[1]);
  385.                 frames[numFrames].startTime=duration;
  386.                 duration+=frames[numFrames].delayTime;
  387.                 numFrames++;
  388.                 if(numFrames==SHADER_MAX_TEX_ANIM_FRAMES)
  389.                     break;
  390.             }
  391.         }else{
  392.             warn("(in TexAnim::readFromFile() (%s, line %i)): Unknown token '%s'.\n\n", f->filename, f->line, t.tokv[0]);
  393.         }
  394.  
  395.     }
  396.  
  397.     return true;
  398. }
  399.  
  400. bool TexAnim::readRange(Tokenizer* t, int delayTime){
  401.     int first=0;
  402.     int last=0;
  403.     int i;
  404.     char name[256];
  405.  
  406. //    if(sscanf(t->tokv[1], "%i...%i", &first, &last) != 2)
  407. //        return false;
  408.     first=atoi(t->tokv[1]);
  409.     last=atoi(&t->tokv[1][5]);
  410.  
  411.     //printf("READ RANGE: %i...%i  (%s)\n", first, last, t->tokv[1]);
  412.  
  413.     for(i=first; i<=last; i++){
  414.         strcpy(name, t->tokv[0]);
  415.         if(i<10)
  416.             strcat(name, "0");
  417.         sprintf(&name[strlen(name)], "%i", i);
  418.         strcat(name, t->tokv[2]);
  419.         
  420.         frames[numFrames].texture=TextureHandler::getTexture(name);
  421.         frames[numFrames].delayTime=delayTime;
  422.         frames[numFrames].startTime=duration;
  423.         duration+=frames[numFrames].delayTime;
  424.         numFrames++;
  425.         if(numFrames==SHADER_MAX_TEX_ANIM_FRAMES)
  426.             break;
  427.     }
  428.  
  429.     return true;
  430. }
  431.  
  432.  
  433. TexCoordAnim::TexCoordAnim(){
  434.     duration=0;
  435. //    combineMode=SHADER_COMBINE_MODE_ADD;
  436.     uModFunc=NULL;
  437.     vModFunc=NULL;
  438.     uAddFunc=NULL;
  439.     vAddFunc=NULL;
  440. }
  441. TexCoordAnim::~TexCoordAnim(){
  442.     if(uModFunc!=NULL)
  443.         delete uModFunc;
  444.     if(vModFunc!=NULL)
  445.         delete vModFunc;
  446.     if(uAddFunc!=NULL)
  447.         delete uAddFunc;
  448.     if(vAddFunc!=NULL)
  449.         delete vAddFunc;
  450. }
  451.  
  452. void TexCoordAnim::setup(unsigned int time){
  453.     int modTime=0;
  454.     if(duration!=0)
  455.         modTime = time % duration;
  456.  
  457.     float uMod=1.0f;
  458.     float vMod=1.0f;
  459.     float uAdd=0.0f;
  460.     float vAdd=0.0f;
  461.  
  462.     float m[16]={    1.0f, 0.0f, 0.0f, 0.0f, 
  463.                     0.0f, 1.0f, 0.0f, 0.0f, 
  464.                     0.0f, 0.0f, 1.0f, 0.0f,
  465.                     0.0f, 0.0f, 0.0f, 1.0f
  466.                 };
  467.  
  468.     glMatrixMode(GL_TEXTURE);
  469.     glPushMatrix();
  470.  
  471.     if(uModFunc!=NULL)
  472.         uMod=uModFunc->getValue(modTime);
  473.     if(vModFunc!=NULL)
  474.         vMod=vModFunc->getValue(modTime);
  475.     if(uAddFunc!=NULL)
  476.         uAdd=uAddFunc->getValue(modTime);
  477.     if(vAddFunc!=NULL)
  478.         vAdd=vAddFunc->getValue(modTime);
  479.  
  480.     m[0]=uMod;
  481.     m[5]=vMod;
  482.     m[12]=uAdd;
  483.     m[13]=vAdd;
  484. /*
  485.     if(combineMode==SHADER_COMBINE_MODE_ADD){
  486.         m[12]=u;
  487.         m[13]=v;
  488.     //    printf("u: %f, v: %f\n", u, v);
  489.     }else if(combineMode==SHADER_COMBINE_MODE_REPLACE){
  490.         m[0]=0.0f;
  491.         m[5]=0.0f;
  492.         m[12]=u;
  493.         m[13]=v;
  494.     }else if(combineMode==SHADER_COMBINE_MODE_MODULATE){
  495.         m[0]=u;
  496.         m[5]=v;
  497.     }
  498. */    
  499.     glLoadMatrixf(m);
  500.  
  501.     glMatrixMode(GL_MODELVIEW);
  502. }
  503.  
  504. void TexCoordAnim::setdown(){
  505.     glMatrixMode(GL_TEXTURE);
  506.     glPopMatrix();
  507.  
  508.     glMatrixMode(GL_MODELVIEW);
  509.  
  510. }
  511.  
  512. bool TexCoordAnim::readFromFile(File* f){
  513.     char buff[256];
  514.     Tokenizer t(" =\t\n\r\"", "\"");
  515.  
  516.     while(f->readLine( 256, buff, true) != -1){
  517.         //printf("TEXCOORDANIM: line: %s\n", buff);
  518.         t.tokenize(buff);
  519.  
  520.         if(t.tokc==0)
  521.             continue;
  522. /*
  523.         if(t.tokc!=2){
  524.             warn("(in Arena::readFromFile()): Wrong number of tokens in line %i (needed 2 but read %i).\n\n", line, t.tokc);
  525.             continue;
  526.         }
  527. */
  528.         if(streq(t.tokv[0], "uMod") && t.tokc>1){
  529.             uModFunc=new AnimFunction(t.tokc-1, &t.tokv[1]);
  530.             if(uModFunc->samples[uModFunc->numSamples-1].time > duration)
  531.                 duration=uModFunc->samples[uModFunc->numSamples-1].time;
  532.         }else if(streq(t.tokv[0], "vMod") && t.tokc>1){
  533.             vModFunc=new AnimFunction(t.tokc-1, &t.tokv[1]);
  534.             if(vModFunc->samples[vModFunc->numSamples-1].time > duration)
  535.                 duration=vModFunc->samples[vModFunc->numSamples-1].time;
  536.         }else if(streq(t.tokv[0], "uAdd") && t.tokc>1){
  537.             uAddFunc=new AnimFunction(t.tokc-1, &t.tokv[1]);
  538.             if(uAddFunc->samples[uAddFunc->numSamples-1].time > duration)
  539.                 duration=uAddFunc->samples[uAddFunc->numSamples-1].time;
  540.         }else if(streq(t.tokv[0], "vAdd") && t.tokc>1){
  541.             vAddFunc=new AnimFunction(t.tokc-1, &t.tokv[1]);
  542.             if(vAddFunc->samples[vAddFunc->numSamples-1].time > duration)
  543.                 duration=vAddFunc->samples[vAddFunc->numSamples-1].time;
  544. /*        }else if(streq(t.tokv[0], "combineMode")){
  545.             if(streq(t.tokv[1], "ADD")){
  546.                 combineMode=SHADER_COMBINE_MODE_ADD;
  547.             }else if(streq(t.tokv[1], "MODULATE")){
  548.                 combineMode=SHADER_COMBINE_MODE_MODULATE;
  549.             }else if(streq(t.tokv[1], "REPLACE")){
  550.                 combineMode=SHADER_COMBINE_MODE_REPLACE;
  551.             }
  552. */
  553.         }else if(streq(t.tokv[0], "{")){
  554.             continue;
  555.         }else if(streq(t.tokv[0], "}")){
  556.             break;//return true;
  557.         }else{
  558.             warn("(in TexCoordAnim::readFromFile() (%s, line %i)): Unknown token '%s'.\n\n", f->filename, f->line, t.tokv[0]);
  559.         }
  560.     }
  561.  
  562.     return true;
  563. }
  564.  
  565.  
  566.  
  567. MapChannelOptions::MapChannelOptions(){
  568.     texUnit=GL_TEXTURE0_ARB;
  569.     map=NULL;
  570.     texAnim=NULL;
  571.     texCoordAnim=NULL;
  572.     texMode=GL_MODULATE;
  573. }
  574.  
  575. MapChannelOptions::~MapChannelOptions(){
  576.     if(texAnim!=NULL)
  577.         delete texAnim;
  578.     if(texCoordAnim!=NULL)
  579.         delete texCoordAnim;
  580.     if(map!=NULL)
  581.         TextureHandler::releaseTexture(map);
  582. }
  583.  
  584. void MapChannelOptions::setup(unsigned int time){
  585.     if(map!=NULL){
  586.         glEnable(GL_TEXTURE_2D);
  587.         glBindTexture(GL_TEXTURE_2D, map->texName);
  588.         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texMode);
  589.     }else if(texAnim!=NULL){
  590.         glEnable(GL_TEXTURE_2D);
  591.         texAnim->setup(time);
  592.         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, texMode);
  593.     }
  594.  
  595.     if(texCoordAnim!=NULL){
  596.         texCoordAnim->setup(time);
  597.     }
  598. }
  599.  
  600. void MapChannelOptions::setdown(){
  601.     if(map!=NULL || texAnim!=NULL){
  602.         glDisable(GL_TEXTURE_2D);
  603.     }
  604.  
  605.     if(texCoordAnim!=NULL){
  606.         texCoordAnim->setdown();
  607.     }
  608. }
  609.  
  610. bool MapChannelOptions::readFromFile(File* f){
  611.     char buff[256];
  612.     Tokenizer t(" =\t\n\r\"|", "\"");
  613.  
  614.     while(f->readLine(256, buff, true) != -1){
  615.         //printf("MAP: line: %s\n", buff);
  616.         t.tokenize(buff);
  617.  
  618.         if(t.tokc==0)
  619.             continue;
  620. /*
  621.         if(t.tokc!=2){
  622.             warn("(in Arena::readFromFile()): Wrong number of tokens in line %i (needed 2 but read %i).\n\n", line, t.tokc);
  623.             continue;
  624.         }
  625. */
  626.         if(streq(t.tokv[0], "texMode")){
  627.             if(t.tokc==2){
  628.                 if(streq(t.tokv[1], "ADD")){
  629.                     texMode=GL_ADD;
  630.                 }else if(streq(t.tokv[1], "MODULATE")){
  631.                     texMode=GL_MODULATE;
  632.                 }else if(streq(t.tokv[1], "REPLACE")){
  633.                     texMode=GL_REPLACE;
  634.                 }else if(streq(t.tokv[1], "DECAL")){
  635.                     texMode=GL_DECAL;
  636.                 }else if(streq(t.tokv[1], "BLEND")){
  637.                     texMode=GL_BLEND;
  638.                 }else{
  639.                     warn("(in MapChannelOptions::readFromFile() (%s, line %i)): Unknown texmode '%s'.\n\n", f->filename, f->line, t.tokv[1]);
  640.                 }
  641.             }else{
  642.                 warn("(in MapChannelOptions::readFromFile() (%s, line %i)): Expected texMode identifier after token 'texMode'.\n\n", f->filename, f->line);
  643.             }
  644.         }else if(streq(t.tokv[0], "map")){
  645.             if(t.tokc==2){
  646.                 map=TextureHandler::getTexture(t.tokv[1]);
  647.             }else{
  648.                 warn("(in MapChannelOptions::readFromFile() (%s, line %i)): Expected map filename after token 'map'.\n\n", f->filename, f->line);
  649.             }
  650.         }else if(streq(t.tokv[0], "texAnim")){
  651.             texAnim=new TexAnim();
  652.             texAnim->readFromFile(f);
  653.         }else if(streq(t.tokv[0], "texCoordAnim")){
  654.             texCoordAnim=new TexCoordAnim();
  655.             texCoordAnim->readFromFile(f);
  656.  
  657.         }else if(streq(t.tokv[0], "{")){
  658.             continue;
  659.         }else if(streq(t.tokv[0], "}")){
  660.             break;//return true;
  661.         }else{
  662.             warn("(in MapChannelOptions::readFromFile() (%s, line %i)): Unknown token '%s'.\n\n", f->filename, f->line, t.tokv[0]);
  663.         }
  664.     }
  665.  
  666.     return true;
  667. }
  668.  
  669.  
  670.  
  671. Shader::Shader(const char* filename){
  672.     this->filename=findShaderForImageFile(filename);
  673.  
  674.     name=NULL;
  675.     base=NULL;
  676.     mapChannel1=NULL;
  677.     mapChannel2=NULL;
  678.  
  679.     if(this->filename==NULL){
  680.         error("(in Shader::Shader()): Couldn't find shader for image file '%s'.\n\n", filename);
  681.         return;
  682.     }
  683.  
  684.     File* f=new File(this->filename, "rt");
  685.     if(f->isOpen()){
  686.         readFromFile(f);
  687.         f->close();
  688.         log("Shader loaded: '%s'.\n", name);
  689.     }else{
  690.         error("(in Shader::Shader()): Couldn't open file '%s'.\n\n", this->filename);
  691.     }
  692. }
  693.  
  694. Shader::~Shader(){
  695.     if(filename!=NULL){
  696.         delete filename;
  697.     }
  698.     if(name!=NULL){
  699.         delete name;
  700.     }
  701.     if(base!=NULL){
  702.         delete base;
  703.     }
  704.     if(mapChannel1!=NULL){
  705.         delete mapChannel1;
  706.     }
  707.     if(mapChannel2!=NULL){
  708.         delete mapChannel2;
  709.     }
  710. }
  711.  
  712. char* Shader::findShaderForImageFile(const char* filename){
  713.     Tokenizer t(filename, ".", "");
  714.     char buff[256];
  715.  
  716.     strcpy(buff, t.tokv[0]);
  717.     strcat(buff, ".shader");
  718.  
  719.     return File::searchAndCreatePath(buff, Renderer::info.var.textureSearchPath);
  720. }
  721.  
  722.  
  723.  
  724. void Shader::setup(unsigned int time){
  725.     if(base!=NULL)
  726.         base->setup(time);
  727.     if(mapChannel1!=NULL){
  728.         mapChannel1->setup(time);
  729.     }
  730.     if(mapChannel2!=NULL && _glActiveTextureARB!=NULL){
  731.         _glActiveTextureARB(GL_TEXTURE1_ARB);
  732.         mapChannel2->setup(time);
  733.         _glActiveTextureARB(GL_TEXTURE0_ARB);
  734.     }
  735. }
  736.  
  737. void Shader::setdown(){
  738.     if(base!=NULL)
  739.         base->setdown();
  740.     if(mapChannel1!=NULL){
  741.         mapChannel1->setdown();
  742.     }
  743.     if(mapChannel2!=NULL && _glActiveTextureARB!=NULL){
  744.         _glActiveTextureARB(GL_TEXTURE1_ARB);
  745.         mapChannel2->setdown();
  746.         _glActiveTextureARB(GL_TEXTURE0_ARB);
  747.     }
  748. }
  749.  
  750. bool Shader::readFromFile(File* f){
  751.     char buff[256];
  752.     Tokenizer t(" =\t\n\r\"", "\"");
  753.  
  754.     while(f->readLine(256, buff, true) != -1){
  755.         
  756.         //printf("SHADER: line: %s\n", buff);
  757.         t.tokenize(buff);
  758.  
  759.         if(t.tokc==0)
  760.             continue;
  761. /*
  762.         if(t.tokc!=2){
  763.             warn("(in Arena::readFromFile()): Wrong number of tokens in line %i (needed 2 but read %i).\n\n", line, t.tokc);
  764.             continue;
  765.         }
  766. */
  767.         if(streq(t.tokv[0], "shader")){
  768.             if(t.tokc==2){
  769.                 name=newString(t.tokv[1]);
  770.             }else{
  771.                 warn("(in Shader::readFromFile() (%s, line %i)): Expected name after token 'shader'.\n\n", f->filename, f->line);
  772.                 name=newString("unnamed");
  773.             }
  774.         }else if(streq(t.tokv[0], "base")){
  775.             base=new BaseOptions();
  776.             base->readFromFile(f);
  777.         }else if(streq(t.tokv[0], "mapChannel1")){
  778.             mapChannel1=new MapChannelOptions();
  779.             mapChannel1->readFromFile(f);
  780.         }else if(streq(t.tokv[0], "mapChannel2")){
  781.             mapChannel2=new MapChannelOptions();
  782.             mapChannel2->readFromFile(f);
  783.  
  784.         }else if(streq(t.tokv[0], "{")){
  785.             continue;
  786.         }else if(streq(t.tokv[0], "}")){
  787.             break;//return true;
  788.         }else{
  789.             warn("(in Shader::readFromFile() (%s, line %i)): Unknown token '%s'.\n\n", f->filename, f->line, t.tokv[0]);
  790.         }
  791.     }
  792.  
  793.     return true;
  794. }
  795.  
  796.