1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkUniformVariables.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 
16 #include "vtkUniformVariables.h"
17 #include "vtkgl.h"
18 #include <cassert>
19 #include "vtkObjectFactory.h"
20 #include "vtkOpenGLError.h"
21 
22 #include <vtksys/stl/map>
23 
24 //-----------------------------------------------------------------------------
25 vtkStandardNewMacro(vtkUniformVariables);
26 
27 class ltstr
28 {
29 public:
operator ()(const char * s1,const char * s2) const30   bool operator()(const char* s1, const char* s2) const
31   {
32     return strcmp(s1, s2) < 0;
33   }
34 };
35 
36 class vtkUniform
37 {
38 public:
39 
40   // just because dynamic__cast is forbidden in VTK. Sucks.
41   enum
42   {
43     ClassTypeVectorInt=0,
44     ClassTypeVectorFloat=1,
45     ClassTypeMatrix=2,
46     ClassTypeArrayInt=3,
47     ClassTypeArrayFloat=4
48   };
49 
GetClassType() const50   int GetClassType() const
51     {
52       return this->ClassType;
53     }
54 
vtkUniform()55   vtkUniform()
56     {
57       this->ClassType=-1;
58       this->Name=0;
59     }
60 
GetName() const61   const char *GetName() const
62     {
63       return this->Name;
64     }
65 
SetName(const char * n)66   void SetName(const char *n)
67     {
68       if(this->Name==0 && n==0)
69         {
70         return;
71         }
72       if(this->Name!=0 && n!=0 && strcmp(this->Name,n)==0)
73         {
74         return;
75         }
76       if(this->Name!=0)
77         {
78         delete[] this->Name;
79         }
80       if(n!=0) // copy
81         {
82          size_t l=strlen(n)+1;
83          this->Name=new char[l];
84          strncpy(this->Name,n,l);
85         }
86       else
87         {
88         this->Name=0;
89         }
90     }
91 
~vtkUniform()92   virtual ~vtkUniform()
93     {
94       if(this->Name!=0)
95         {
96         delete[] Name;
97         }
98     }
99 
100   virtual void Send(int location)=0;
101 
102   virtual void PrintSelf(ostream &os, vtkIndent indent)=0;
103 
104   virtual vtkUniform *Clone() const=0;
105 
106 protected:
107   char *Name;
108 
109   int ClassType; // just because dynamic__cast is forbidden in VTK. Sucks.
110 };
111 
112 class vtkUniformVectorInt : public vtkUniform
113 {
114 public:
vtkUniformVectorInt(int size,int * values)115   vtkUniformVectorInt(int size,
116                       int *values)
117     {
118       this->ClassType=ClassTypeVectorInt;
119       this->Size=size;
120       this->Values=new int[size];
121       int i=0;
122       while(i<size)
123         {
124         this->Values[i]=values[i];
125         ++i;
126         }
127     }
~vtkUniformVectorInt()128   virtual ~vtkUniformVectorInt()
129     {
130       delete[] this->Values;
131     }
132 
GetSize()133   int GetSize()
134     {
135       return this->Size;
136     }
137 
SetValues(int * values)138   void SetValues(int *values)
139     {
140       int i=0;
141       while(i<this->Size)
142         {
143         this->Values[i]=values[i];
144         ++i;
145         }
146     }
147 
GetValues()148   const int *GetValues()
149     {
150      return this->Values;
151     }
152 
Send(int location)153    virtual void Send(int location)
154     {
155       switch(this->Size)
156         {
157         case 1:
158           vtkgl::Uniform1i(location,this->Values[0]);
159           break;
160         case 2:
161           vtkgl::Uniform2i(location,this->Values[0],this->Values[1]);
162           break;
163         case 3:
164           vtkgl::Uniform3i(location,this->Values[0],this->Values[1],
165                            this->Values[2]);
166           break;
167         case 4:
168           vtkgl::Uniform4i(location,this->Values[0],this->Values[1],
169                            this->Values[2],this->Values[3]);
170           break;
171         }
172       vtkOpenGLStaticCheckErrorMacro("failed at glUniform*i");
173     }
174 
PrintSelf(ostream & os,vtkIndent indent)175   virtual void PrintSelf(ostream &os, vtkIndent indent)
176     {
177       os << indent << this->Name << " (uniform" << this->Size << "i): ";
178       int i=0;
179       while(i<this->Size)
180         {
181         os << this->Values[i];
182         if(i<(this->Size-1))
183           {
184           os <<",";
185           }
186         ++i;
187         }
188       os << endl;
189     }
190 
Clone() const191   virtual vtkUniform *Clone() const
192     {
193       vtkUniformVectorInt *result=new vtkUniformVectorInt(this->Size,
194                                                           this->Values);
195       result->SetName(this->Name);
196       return result;
197     }
198 
199 protected:
200   int Size;
201   int *Values;
202 };
203 
204 class vtkUniformVectorFloat : public vtkUniform
205 {
206 public:
vtkUniformVectorFloat(int size,float * values)207   vtkUniformVectorFloat(int size,
208                         float *values)
209     {
210       this->ClassType=ClassTypeVectorFloat;
211       this->Size=size;
212       this->Values=new float[size];
213       int i=0;
214       while(i<size)
215         {
216         this->Values[i]=values[i];
217         ++i;
218         }
219     }
220 
~vtkUniformVectorFloat()221   virtual ~vtkUniformVectorFloat()
222     {
223       delete[] this->Values;
224     }
225 
GetSize()226   int GetSize()
227     {
228       return this->Size;
229     }
230 
SetValues(float * values)231   void SetValues(float *values)
232     {
233       int i=0;
234       while(i<this->Size)
235         {
236         this->Values[i]=values[i];
237         ++i;
238         }
239     }
240 
GetValues()241   const float *GetValues()
242     {
243       return this->Values;
244     }
245 
Send(int location)246   virtual void Send(int location)
247     {
248       switch(this->Size)
249         {
250         case 1:
251           vtkgl::Uniform1f(location,this->Values[0]);
252           break;
253         case 2:
254           vtkgl::Uniform2f(location,this->Values[0],this->Values[1]);
255           break;
256         case 3:
257           vtkgl::Uniform3f(location,this->Values[0],this->Values[1],
258                            this->Values[2]);
259           break;
260         case 4:
261           vtkgl::Uniform4f(location,this->Values[0],this->Values[1],
262                            this->Values[2],this->Values[3]);
263           break;
264         }
265       vtkOpenGLStaticCheckErrorMacro("failed at glUniform*f");
266     }
267 
PrintSelf(ostream & os,vtkIndent indent)268   virtual void PrintSelf(ostream &os, vtkIndent indent)
269     {
270       os << indent << this->Name << " (uniform" << this->Size << "f): ";
271       int i=0;
272       while(i<this->Size)
273         {
274         os << this->Values[i];
275         if(i<(this->Size-1))
276           {
277           os <<",";
278           }
279         ++i;
280         }
281       os << endl;
282     }
283 
Clone() const284   virtual vtkUniform *Clone() const
285     {
286       vtkUniformVectorFloat *result=new vtkUniformVectorFloat(this->Size,
287                                                               this->Values);
288       result->SetName(this->Name);
289       return result;
290     }
291 
292 protected:
293   int Size;
294   float *Values;
295 };
296 
297 class vtkUniformArrayInt : public vtkUniform
298 {
299 public:
vtkUniformArrayInt(int size,int arraySize,int * values)300   vtkUniformArrayInt(int size,
301                      int arraySize,
302                      int *values)
303     {
304       this->ClassType=ClassTypeArrayInt;
305       this->Size=size;
306       this->ArraySize=arraySize;
307       this->Values=new GLint[size*arraySize];
308       int i=0;
309       while(i<this->Size*this->ArraySize)
310         {
311         this->Values[i]=values[i];
312         ++i;
313         }
314     }
315 
316   // this constructor is used inside Clone()
317   // It is required because GLint is long on Mac, not int.
vtkUniformArrayInt(int size,int arraySize,const GLint * values)318   vtkUniformArrayInt(int size,
319                      int arraySize,
320                      const GLint *values)
321     {
322       this->ClassType=ClassTypeArrayInt;
323       this->Size=size;
324       this->ArraySize=arraySize;
325       this->Values=new GLint[size*arraySize];
326       int i=0;
327       while(i<this->Size*this->ArraySize)
328         {
329         this->Values[i]=values[i];
330         ++i;
331         }
332     }
333 
~vtkUniformArrayInt()334   virtual ~vtkUniformArrayInt()
335     {
336       delete[] this->Values;
337     }
338 
GetSize()339   int GetSize()
340     {
341       return this->Size;
342     }
343 
GetArraySize()344   int GetArraySize()
345     {
346       return this->ArraySize;
347     }
348 
SetValues(int * values)349   void SetValues(int *values)
350     {
351       int i=0;
352       while(i<this->Size*this->ArraySize)
353         {
354         this->Values[i]=values[i];
355         ++i;
356         }
357     }
358 
GetValues()359   const GLint *GetValues()
360     {
361       return this->Values;
362     }
363 
Send(int location)364   virtual void Send(int location)
365     {
366       switch(this->Size)
367         {
368         case 1:
369           vtkgl::Uniform1iv(location,this->ArraySize,this->Values);
370           break;
371         case 2:
372           vtkgl::Uniform2iv(location,this->ArraySize,this->Values);
373           break;
374         case 3:
375           vtkgl::Uniform3iv(location,this->ArraySize,this->Values);
376           break;
377         case 4:
378           vtkgl::Uniform4iv(location,this->ArraySize,this->Values);
379           break;
380         }
381       vtkOpenGLStaticCheckErrorMacro("failed at glUniform*iv");
382     }
383 
PrintSelf(ostream & os,vtkIndent indent)384   virtual void PrintSelf(ostream &os, vtkIndent indent)
385     {
386       os << indent << this->Name << " (uniform" << this->Size << "iv[" << this->ArraySize << "]): ";
387       int j=0;
388       while(j<this->ArraySize)
389         {
390         os << "(";
391         int i=0;
392         while(i<this->Size)
393           {
394           os << this->Values[i];
395           if(i<(this->Size-1))
396             {
397             os <<",";
398             }
399           ++i;
400           }
401         os << endl;
402         ++j;
403         }
404     }
405 
Clone() const406   virtual vtkUniform *Clone() const
407     {
408       vtkUniformArrayInt *result=new vtkUniformArrayInt(this->Size,
409                                                         this->ArraySize,
410                                                         this->Values);
411       result->SetName(this->Name);
412       return result;
413     }
414 
415 protected:
416   int Size;  // size of element (eq. to float, vec2, vec2, vec4)
417   int ArraySize; // number of elements
418   GLint *Values; // GLint is long on Mac
419 };
420 
421 class vtkUniformArrayFloat : public vtkUniform
422 {
423 public:
vtkUniformArrayFloat(int size,int arraySize,float * values)424   vtkUniformArrayFloat(int size,
425                        int arraySize,
426                        float *values)
427     {
428       this->ClassType=ClassTypeArrayFloat;
429       this->Size=size;
430       this->ArraySize=arraySize;
431       this->Values=new float[size*arraySize];
432       int i=0;
433       while(i<this->Size*this->ArraySize)
434         {
435         this->Values[i]=values[i];
436         ++i;
437         }
438     }
439 
~vtkUniformArrayFloat()440   virtual ~vtkUniformArrayFloat()
441     {
442       delete[] this->Values;
443     }
444 
GetSize()445   int GetSize()
446     {
447       return this->Size;
448     }
449 
GetArraySize()450   int GetArraySize()
451     {
452       return this->ArraySize;
453     }
454 
SetValues(float * values)455   void SetValues(float *values)
456     {
457       int i=0;
458       while(i<this->Size*this->ArraySize)
459         {
460         this->Values[i]=values[i];
461         ++i;
462         }
463     }
464 
GetValues()465   const float *GetValues()
466     {
467       return this->Values;
468     }
469 
Send(int location)470   virtual void Send(int location)
471     {
472       switch(this->Size)
473         {
474         case 1:
475           vtkgl::Uniform1fv(location,this->ArraySize,this->Values);
476           break;
477         case 2:
478           vtkgl::Uniform2fv(location,this->ArraySize,this->Values);
479           break;
480         case 3:
481           vtkgl::Uniform3fv(location,this->ArraySize,this->Values);
482           break;
483         case 4:
484           vtkgl::Uniform4fv(location,this->ArraySize,this->Values);
485           break;
486         }
487       vtkOpenGLStaticCheckErrorMacro("failed at glUniform*fv");
488     }
489 
PrintSelf(ostream & os,vtkIndent indent)490   virtual void PrintSelf(ostream &os, vtkIndent indent)
491     {
492       os << indent << this->Name << " (uniform" << this->Size << "fv[" << this->ArraySize << "]): ";
493       int j=0;
494       while(j<this->ArraySize)
495         {
496         os << "(";
497         int i=0;
498         while(i<this->Size)
499           {
500           os << this->Values[i];
501           if(i<(this->Size-1))
502             {
503             os <<",";
504             }
505           ++i;
506           }
507         os << endl;
508         ++j;
509         }
510     }
511 
Clone() const512   virtual vtkUniform *Clone() const
513     {
514       vtkUniformArrayFloat *result=new vtkUniformArrayFloat(this->Size,
515                                                             this->ArraySize,
516                                                             this->Values);
517       result->SetName(this->Name);
518       return result;
519     }
520 
521 protected:
522   int Size;  // size of element (eq. to float, vec2, vec2, vec4)
523   int ArraySize; // number of elements
524   float *Values;
525 };
526 
527 // rows or columns are 2,3,4.
528 class vtkUniformMatrix : public vtkUniform
529 {
530 public:
vtkUniformMatrix(int rows,int columns,float * values)531   vtkUniformMatrix(int rows,
532                    int columns,
533                    float *values)
534     {
535       this->ClassType=ClassTypeMatrix;
536       this->Rows=rows;
537       this->Columns=columns;
538       this->Values=new float[rows*columns];
539       int i=0;
540       while(i<rows)
541         {
542         int j=0;
543         while(j<columns)
544           {
545           int index=i*columns+j;
546           this->Values[index]=values[index];
547           ++j;
548           }
549         ++i;
550         }
551     }
552 
~vtkUniformMatrix()553   ~vtkUniformMatrix()
554     {
555       delete[] this->Values;
556     }
557 
GetRows()558   int GetRows()
559     {
560       return this->Rows;
561     }
562 
GetColumns()563   int GetColumns()
564     {
565       return this->Columns;
566     }
567 
SetValues(float * values)568   void SetValues(float *values)
569     {
570       int i=0;
571       while(i<this->Rows)
572         {
573         int j=0;
574         while(j<this->Columns)
575           {
576           int index=i*this->Columns+j;
577           this->Values[index]=values[index];
578           ++j;
579           }
580         ++i;
581         }
582     }
583 
GetValues()584   const float* GetValues()
585     {
586       return this->Values;
587     }
588 
Send(int location)589   virtual void Send(int location)
590     {
591       switch(this->Rows)
592         {
593         case 2:
594           switch(this->Columns)
595             {
596             case 2:
597               vtkgl::UniformMatrix2fv(location,1,GL_FALSE,this->Values);
598               break;
599             case 3:
600               vtkgl::UniformMatrix2x3fv(location,1,GL_FALSE,this->Values);
601               break;
602             case 4:
603               vtkgl::UniformMatrix2x4fv(location,1,GL_FALSE,this->Values);
604               break;
605             }
606           break;
607         case 3:
608            switch(this->Columns)
609             {
610             case 2:
611               vtkgl::UniformMatrix3x2fv(location,1,GL_FALSE,this->Values);
612               break;
613             case 3:
614               vtkgl::UniformMatrix3fv(location,1,GL_FALSE,this->Values);
615               break;
616             case 4:
617               vtkgl::UniformMatrix3x4fv(location,1,GL_FALSE,this->Values);
618               break;
619             }
620            break;
621         case 4:
622           switch(this->Columns)
623             {
624             case 2:
625               vtkgl::UniformMatrix4x2fv(location,1,GL_FALSE,this->Values);
626               break;
627             case 3:
628               vtkgl::UniformMatrix4x3fv(location,1,GL_FALSE,this->Values);
629               break;
630             case 4:
631               vtkgl::UniformMatrix4fv(location,1,GL_FALSE,this->Values);
632               break;
633             }
634           break;
635         }
636       vtkOpenGLStaticCheckErrorMacro("failed at glUniformMatrix*fv");
637     }
638 
PrintSelf(ostream & os,vtkIndent indent)639   virtual void PrintSelf(ostream &os, vtkIndent indent)
640     {
641       os << indent << this->Name << " (matrix " << this->Rows << "x"
642          << this->Columns << "): ";
643 
644       int i=0;
645       while(i<this->Rows)
646         {
647         int j=0;
648         while(j<this->Columns)
649           {
650           int index=i*this->Columns+j;
651           os << this->Values[index];
652           if(j<(this->Columns-1))
653             os << ",";
654           ++j;
655           }
656         os << endl;
657         ++i;
658         }
659     }
660 
Clone() const661   virtual vtkUniform *Clone() const
662     {
663       vtkUniformMatrix *result=new vtkUniformMatrix(this->Rows,this->Columns,
664                                                     this->Values);
665       result->SetName(this->Name);
666       return result;
667     }
668 
669 protected:
670   float *Values;
671   int Rows;
672   int Columns;
673 };
674 
675 typedef vtksys_stl::map<const char *, vtkUniform *, ltstr> UniformMap;
676 typedef vtksys_stl::map<const char *, vtkUniform *, ltstr>::iterator UniformMapIt;
677 
678 class vtkUniformVariablesMap
679 {
680 public:
681   UniformMap Map;
682   UniformMapIt It; // used for external iteration.
683 
~vtkUniformVariablesMap()684   ~vtkUniformVariablesMap()
685     {
686       UniformMapIt i=this->Map.begin();
687       UniformMapIt e=this->Map.end();
688       while(i!=e)
689         {
690         vtkUniform *u=(*i).second;
691         if(u!=0)
692           {
693           delete u;
694           }
695         ++i;
696         }
697     }
698 };
699 
700 // ----------------------------------------------------------------------------
vtkUniformVariables()701 vtkUniformVariables::vtkUniformVariables()
702 {
703   this->Map=new vtkUniformVariablesMap;
704 }
705 
706 // ----------------------------------------------------------------------------
~vtkUniformVariables()707 vtkUniformVariables::~vtkUniformVariables()
708 {
709   delete this->Map;
710 }
711 
712 // ----------------------------------------------------------------------------
SetUniformi(const char * name,int numberOfComponents,int * value)713 void vtkUniformVariables::SetUniformi(const char *name,
714                                       int numberOfComponents,
715                                       int *value)
716 {
717   assert("pre: name_exists" && name!=0);
718   assert("pre: value_exists" && value!=0);
719   assert("pre: valid_numberOfComponents" && numberOfComponents>=1 && numberOfComponents<=4);
720 
721   UniformMapIt cur=this->Map->Map.find(name);
722 
723   if(cur!=this->Map->Map.end())
724     {
725     vtkUniform *u=(*cur).second;
726     vtkUniformVectorInt *ui=0;
727     if(u->GetClassType()==vtkUniform::ClassTypeVectorInt)
728       {
729       ui=static_cast<vtkUniformVectorInt *>(u);
730       }
731     if(ui==0)
732       {
733       vtkErrorMacro(<<"try to overwrite a value with different type.");
734       }
735     else
736       {
737       if(ui->GetSize()!=numberOfComponents)
738         {
739         vtkErrorMacro(<<"try to overwrite a value of same type but different number of components.");
740         }
741       else
742         {
743         bool changed=false;
744         int i=0;
745         while(!changed && i<numberOfComponents)
746           {
747           changed=value[i]!=ui->GetValues()[i];
748           ++i;
749           }
750         if(changed)
751           {
752           ui->SetValues(value);
753           this->Modified();
754           }
755         }
756       }
757     }
758   else
759     {
760     vtkUniform *u=0;
761     u=new vtkUniformVectorInt(numberOfComponents,value);
762     u->SetName(name);
763 
764     vtksys_stl::pair<const char *, vtkUniform *> p;
765     p.first=u->GetName(); // cannot be `name' because
766     // we don't manage this pointer.
767     p.second=u;
768 
769     this->Map->Map.insert(p);
770     this->Modified();
771     }
772 }
773 
774 // ----------------------------------------------------------------------------
SetUniformf(const char * name,int numberOfComponents,float * value)775 void vtkUniformVariables::SetUniformf(const char *name,
776                                       int numberOfComponents,
777                                       float *value)
778 {
779   assert("pre: name_exists" && name!=0);
780   assert("pre: value_exists" && value!=0);
781   assert("pre: valid_numberOfComponents" && numberOfComponents>=1 && numberOfComponents<=4);
782 
783   UniformMapIt cur=this->Map->Map.find(name);
784 
785   if(cur!=this->Map->Map.end())
786     {
787     vtkUniform *u=(*cur).second;
788     vtkUniformVectorFloat *uf=0;
789     if(u->GetClassType()==vtkUniform::ClassTypeVectorFloat)
790       {
791       uf=static_cast<vtkUniformVectorFloat *>(u);
792       }
793     if(uf==0)
794       {
795       vtkErrorMacro(<<"try to overwrite a value with different type.");
796       }
797     else
798       {
799       if(uf->GetSize()!=numberOfComponents)
800         {
801         vtkErrorMacro(<<"try to overwrite a value of same type but different number of components.");
802         }
803       else
804         {
805         bool changed=false;
806         int i=0;
807         while(!changed && i<numberOfComponents)
808           {
809           changed=value[i]!=uf->GetValues()[i];
810           ++i;
811           }
812         if(changed)
813           {
814           uf->SetValues(value);
815           this->Modified();
816           }
817         }
818       }
819     }
820   else
821     {
822     vtkUniform *u=0;
823     u=new vtkUniformVectorFloat(numberOfComponents,value);
824     u->SetName(name);
825 
826     vtksys_stl::pair<const char *, vtkUniform *> p;
827     p.first=u->GetName(); // cannot be `name' because
828     // we don't manage this pointer.
829     p.second=u;
830 
831     this->Map->Map.insert(p);
832     this->Modified();
833     }
834 }
835 
836 // ----------------------------------------------------------------------------
SetUniformiv(const char * name,int numberOfComponents,int numberOfElements,int * value)837 void vtkUniformVariables::SetUniformiv(const char *name,
838                                        int numberOfComponents,
839                                        int numberOfElements,
840                                        int *value)
841 {
842   assert("pre: name_exists" && name!=0);
843   assert("pre: value_exists" && value!=0);
844   assert("pre: valid_numberOfComponents" && numberOfComponents>=1 && numberOfComponents<=4);
845   assert("pre: valid_numberOfElements" && numberOfElements>=1);
846 
847   UniformMapIt cur=this->Map->Map.find(name);
848 
849   if(cur!=this->Map->Map.end())
850     {
851     vtkUniform *u=(*cur).second;
852     vtkUniformArrayInt *ui=0;
853     if(u->GetClassType()==vtkUniform::ClassTypeArrayInt)
854       {
855       ui=static_cast<vtkUniformArrayInt *>(u);
856       }
857     if(ui==0)
858       {
859       vtkErrorMacro(<<"try to overwrite a value with different type.");
860       }
861     else
862       {
863       if(ui->GetSize()!=numberOfComponents)
864         {
865         vtkErrorMacro(<<"try to overwrite a value of same type but different number of components.");
866         }
867       if(ui->GetArraySize()!=numberOfElements)
868         {
869         vtkErrorMacro(<<"try to overwrite a value of same type but different number of elements.");
870         }
871       else
872         {
873         bool changed=false;
874         int i=0;
875         while(!changed && i<numberOfComponents*numberOfElements)
876           {
877           changed=value[i]!=ui->GetValues()[i];
878           ++i;
879           }
880         if(changed)
881           {
882           ui->SetValues(value);
883           this->Modified();
884           }
885         }
886       }
887     }
888   else
889     {
890     vtkUniform *u=0;
891     u=new vtkUniformArrayInt(numberOfComponents,numberOfElements,value);
892     u->SetName(name);
893 
894     vtksys_stl::pair<const char *, vtkUniform *> p;
895     p.first=u->GetName(); // cannot be `name' because
896     // we don't manage this pointer.
897     p.second=u;
898 
899     this->Map->Map.insert(p);
900     this->Modified();
901     }
902 }
903 
904 // ----------------------------------------------------------------------------
SetUniformfv(const char * name,int numberOfComponents,int numberOfElements,float * value)905 void vtkUniformVariables::SetUniformfv(const char *name,
906                                        int numberOfComponents,
907                                        int numberOfElements,
908                                        float *value)
909 {
910   assert("pre: name_exists" && name!=0);
911   assert("pre: value_exists" && value!=0);
912   assert("pre: valid_numberOfComponents" && numberOfComponents>=1 && numberOfComponents<=4);
913   assert("pre: valid_numberOfElements" && numberOfElements>=1);
914 
915   UniformMapIt cur=this->Map->Map.find(name);
916 
917   if(cur!=this->Map->Map.end())
918     {
919     vtkUniform *u=(*cur).second;
920     vtkUniformArrayFloat *uf=0;
921     if(u->GetClassType()==vtkUniform::ClassTypeArrayFloat)
922       {
923       uf=static_cast<vtkUniformArrayFloat *>(u);
924       }
925     if(uf==0)
926       {
927       vtkErrorMacro(<<"try to overwrite a value with different type.");
928       }
929     else
930       {
931       if(uf->GetSize()!=numberOfComponents)
932         {
933         vtkErrorMacro(<<"try to overwrite a value of same type but different number of components.");
934         }
935       if(uf->GetArraySize()!=numberOfElements)
936         {
937         vtkErrorMacro(<<"try to overwrite a value of same type but different number of elements.");
938         }
939       else
940         {
941         bool changed=false;
942         int i=0;
943         while(!changed && i<numberOfComponents*numberOfElements)
944           {
945           changed=value[i]!=uf->GetValues()[i];
946           ++i;
947           }
948         if(changed)
949           {
950           uf->SetValues(value);
951           this->Modified();
952           }
953         }
954       }
955     }
956   else
957     {
958     vtkUniform *u=0;
959     u=new vtkUniformArrayFloat(numberOfComponents,numberOfElements,value);
960     u->SetName(name);
961 
962     vtksys_stl::pair<const char *, vtkUniform *> p;
963     p.first=u->GetName(); // cannot be `name' because
964     // we don't manage this pointer.
965     p.second=u;
966 
967     this->Map->Map.insert(p);
968     this->Modified();
969     }
970 }
971 
972 // ----------------------------------------------------------------------------
SetUniformMatrix(const char * name,int rows,int columns,float * value)973 void vtkUniformVariables::SetUniformMatrix(const char *name,
974                                            int rows,
975                                            int columns,
976                                            float *value)
977 {
978   assert("pre: name_exists" && name!=0);
979   assert("pre: value_exists" && value!=0);
980   assert("pre: valid_rows" && rows>=2 && rows<=4);
981   assert("pre: valid_columns" && columns>=2 && columns<=4);
982 
983   UniformMapIt cur=this->Map->Map.find(name);
984 
985   if(cur!=this->Map->Map.end())
986     {
987     vtkUniform *u=(*cur).second;
988     vtkUniformMatrix *um=0;
989     if(u->GetClassType()==vtkUniform::ClassTypeMatrix)
990       {
991       um=static_cast<vtkUniformMatrix *>(u);
992       }
993     if(um==0)
994       {
995       vtkErrorMacro(<<"try to overwrite a value with different type.");
996       }
997     else
998       {
999       if(um->GetRows()!=rows || um->GetColumns()!=columns)
1000         {
1001         vtkErrorMacro(<<"try to overwrite a value of same type but different number of components.");
1002         }
1003       else
1004         {
1005         bool changed=false;
1006         int i=0;
1007         while(!changed && i<rows*columns)
1008           {
1009           changed=value[i]!=um->GetValues()[i];
1010           ++i;
1011           }
1012         if(changed)
1013           {
1014           um->SetValues(value);
1015           this->Modified();
1016           }
1017         }
1018       }
1019     }
1020   else
1021     {
1022     vtkUniform *u=new vtkUniformMatrix(rows,columns,value);
1023     u->SetName(name);
1024     vtksys_stl::pair<const char *, vtkUniform *> p;
1025     p.first=u->GetName(); // cannot be `name' because
1026     // we don't manage this pointer.
1027     p.second=u;
1028     this->Map->Map.insert(p);
1029     this->Modified();
1030     }
1031 }
1032 
1033 // ----------------------------------------------------------------------------
1034 // Description:
1035 // Remove uniform `name' from the list.
RemoveUniform(const char * name)1036 void vtkUniformVariables::RemoveUniform(const char *name)
1037 {
1038   UniformMapIt cur=this->Map->Map.find(name);
1039   if(cur!=this->Map->Map.end())
1040     {
1041     this->Map->Map.erase(cur);
1042     this->Modified();
1043     }
1044 }
1045 
1046 // ----------------------------------------------------------------------------
1047 // Description:
1048 // \pre need a valid OpenGL context and a shader program in use.
Send(const char * name,int uniformIndex)1049 void vtkUniformVariables::Send(const char *name,
1050                                int uniformIndex)
1051 {
1052   UniformMapIt cur=this->Map->Map.find(name);
1053   (*cur).second->Send(uniformIndex);
1054 }
1055 
1056 // ----------------------------------------------------------------------------
1057 // Description:
1058 // Place the internal cursor on the first uniform.
Start()1059 void vtkUniformVariables::Start()
1060 {
1061   this->Map->It=this->Map->Map.begin();
1062 }
1063 
1064 // ----------------------------------------------------------------------------
1065 // Description:
1066 // Is the iteration done?
IsAtEnd()1067 bool vtkUniformVariables::IsAtEnd()
1068 {
1069   return this->Map->It==this->Map->Map.end();
1070 }
1071 
1072 // ----------------------------------------------------------------------------
1073 // Description:
1074 // Name of the uniform at the current cursor position.
1075 // \pre not_done: !this->IsAtEnd()
GetCurrentName()1076 const char *vtkUniformVariables::GetCurrentName()
1077 {
1078   assert("pre: not_done" && !this->IsAtEnd());
1079   return (*this->Map->It).first;
1080 }
1081 
1082 // ----------------------------------------------------------------------------
1083 // Description:
1084 // \pre need a valid OpenGL context and a shader program in use.
1085 // \pre not_done: !this->IsAtEnd()
SendCurrentUniform(int uniformIndex)1086 void vtkUniformVariables::SendCurrentUniform(int uniformIndex)
1087 {
1088   assert("pre: not_done" && !this->IsAtEnd());
1089   (*this->Map->It).second->Send(uniformIndex);
1090 }
1091 
1092 // ----------------------------------------------------------------------------
1093 // Description:
1094 // Move the cursor to the next uniform.
1095 // \pre not_done: !this->IsAtEnd()
Next()1096 void vtkUniformVariables::Next()
1097 {
1098   assert("pre: not_done" && !this->IsAtEnd());
1099   ++this->Map->It;
1100 }
1101 
1102 // ----------------------------------------------------------------------------
1103 // Description:
1104 // Copy all the variables from `other'. Any existing variable will be
1105 // overwritten.
1106 // \pre other_exists: other!=0
1107 // \pre not_self: other!=this
Merge(vtkUniformVariables * other)1108 void vtkUniformVariables::Merge(vtkUniformVariables *other)
1109 {
1110   assert("pre: other_exists" && other != 0);
1111   assert("pre: not_self" && other != this);
1112 
1113   other->Start();
1114   while (!other->IsAtEnd())
1115     {
1116     const char *name = other->GetCurrentName();
1117     UniformMapIt prev = this->Map->Map.find(name);
1118     if (prev != this->Map->Map.end())
1119       {
1120       delete prev->second;
1121       this->Map->Map.erase(prev);
1122       }
1123     vtkUniform* clone = other->Map->It->second->Clone();
1124     this->Map->Map[clone->GetName()] = clone;
1125 
1126     other->Next();
1127     }
1128   if (other->Map->Map.size() > 0)
1129     {
1130     this->Modified();
1131     }
1132 }
1133 
1134 // ----------------------------------------------------------------------------
1135 // Description:
1136 // Copy all the variables from `other'. Any existing variable will be
1137 // deleted first.
1138 // \pre other_exists: other!=0
1139 // \pre not_self: other!=this
DeepCopy(vtkUniformVariables * other)1140 void vtkUniformVariables::DeepCopy(vtkUniformVariables *other)
1141 {
1142   assert("pre: other_exists" && other!=0);
1143   assert("pre: not_self" && other!=this);
1144 
1145   if(this->Map->Map.size()>0)
1146     {
1147     delete this->Map;
1148     this->Map=new vtkUniformVariablesMap;
1149     this->Modified();
1150     }
1151   this->Merge(other);
1152 }
1153 
1154 // ----------------------------------------------------------------------------
RemoveAllUniforms()1155 void vtkUniformVariables::RemoveAllUniforms()
1156 {
1157   if(this->Map->Map.size()>0)
1158     {
1159     delete this->Map;
1160     this->Map=new vtkUniformVariablesMap;
1161     this->Modified();
1162     }
1163 }
1164 
1165 // ----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)1166 void vtkUniformVariables::PrintSelf(ostream& os, vtkIndent indent)
1167 {
1168   this->Superclass::PrintSelf(os,indent);
1169 
1170   this->Start();
1171   while(!this->IsAtEnd())
1172     {
1173     const char *name=this->GetCurrentName();
1174     UniformMapIt cur=this->Map->Map.find(name);
1175     (*cur).second->PrintSelf(os,indent);
1176     this->Next();
1177     }
1178 }
1179