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