1 /****************************************************************************
2 * MeshLab                                                           o o     *
3 * A versatile mesh processing toolbox                             o     o   *
4 *                                                                _   O  _   *
5 * Copyright(C) 2005-2008                                           \/)\/    *
6 * Visual Computing Lab                                            /\/|      *
7 * ISTI - Italian National Research Council                           |      *
8 *                                                                    \      *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 /****************************************************************************
24 History
25 $Log$
26 Revision 1.3  2007/12/11 16:18:56  corsini
27 minor change
28 
29 Revision 1.2  2007/12/03 12:01:04  corsini
30 code restyling
31 
32 
33 ****************************************************************************/
34 
35 // Local headers
36 #include "UniformVar.h"
37 #include "RmXmlParser.h"
38 
39 
UniformVar(QString & _name,QString & _typeString,UniformType _type)40 UniformVar::UniformVar(QString &_name, QString &_typeString, UniformType _type)
41 {
42 	name = _name;
43 	typeString = _typeString;
44 	type = _type;
45 	valid = true;
46 	minSet = false;
47 	maxSet = false;
48 	realminSet = false;
49 	realmaxSet = false;
50 }
51 
setMin(int min)52 void UniformVar::setMin(int min)
53 {
54 	if ((realminSet && min <= irealmin) || !realminSet) {
55 		imin = min;
56 		minSet = true;
57 	}
58 }
59 
setMax(int max)60 void UniformVar::setMax(int max)
61 {
62 	if ((realmaxSet && max >= irealmax) || !realmaxSet) {
63 		imax = max;
64 		maxSet = true;
65 	}
66 }
67 
setMin(float min)68 void UniformVar::setMin(float min)
69 {
70 	if ((realminSet && min <= frealmin) || !realminSet) {
71 		fmin = min;
72 		minSet = true;
73 	}
74 }
75 
setMax(float max)76 void UniformVar::setMax(float max)
77 {
78 	if ((realmaxSet && max >= frealmax) || !realmaxSet) {
79 		fmax = max;
80 		maxSet = true;
81 	}
82 }
83 
testRealMin(int min)84 void UniformVar::testRealMin(int min)
85 {
86 	if (!realminSet || min < irealmin) {
87 		realminSet = true;
88 		irealmin = min;
89 		if (minSet && imin > irealmin)
90 			minSet = false;
91 	}
92 }
93 
testRealMin(float min)94 void UniformVar::testRealMin(float min)
95 {
96 	if (!realminSet || min < frealmin) {
97 		realminSet = true;
98 		frealmin = min;
99 		if (minSet && fmin > frealmin)
100 			minSet = false;
101 	}
102 }
103 
testRealMax(int max)104 void UniformVar::testRealMax(int max)
105 {
106 	if (!realmaxSet || max > irealmax) {
107 		realmaxSet = true;
108 		irealmax = max;
109 		if (maxSet && imax < irealmax)
110 			maxSet = false;
111 	}
112 }
113 
testRealMax(float max)114 void UniformVar::testRealMax(float max)
115 {
116 	if (!realmaxSet || max > irealmax) {
117 		realmaxSet = true;
118 		frealmax = max;
119 		if (maxSet && fmax < frealmax)
120 			maxSet = false;
121 	}
122 }
123 
getUniformKnownButUnimplementedTag(QDomElement & root,QString tag,QString tagname)124 bool UniformVar::getUniformKnownButUnimplementedTag(QDomElement &root, QString tag, QString tagname)
125 {
126 	if (!RmXmlParser::getDomElement(root, tag, tagname).isNull()) {
127 		representerTagName = tag;
128 		return true;
129 	}
130 	return false;
131 }
132 
133 /******************************/
134 /* 3 Common Methods for       */
135 /* xml variable value mining  */
136 /* [boolean][number][texture] */
137 /******************************/
getUniformBooleanVectorFromTag(QDomElement & root,QString tag,int vecsize,bool * vec,bool * found)138 bool UniformVar::getUniformBooleanVectorFromTag(QDomElement &root, QString tag, int vecsize, bool *vec, bool *found)
139 {
140 	QDomElement el = RmXmlParser::getDomElement(root, tag, name);
141 
142 	if(!el.isNull()) {
143 		if (found)
144 			*found = true;
145 		representerTagName = tag;
146 		return UniformVar::getUniformBooleanVectorFromXmlTag(el, vecsize, vec);
147 	}
148 
149 	if (found)
150 		*found = false;
151 	return false;
152 }
153 
getUniformNumberVectorFromTag(QDomElement & root,QString tag,int vecsize,void * vec,bool intOrFloat,bool * found)154 bool UniformVar::getUniformNumberVectorFromTag(QDomElement &root, QString tag, int vecsize, void *vec, bool intOrFloat, bool *found)
155 {
156 	QDomElement el = RmXmlParser::getDomElement(root, tag, name);
157 
158 	if (!el.isNull()) {
159 		if (found)
160 			*found = true;
161 		representerTagName = tag;
162 		return UniformVar::getUniformNumberVectorFromXmlTag(el, vecsize, vec, intOrFloat, this);
163 	}
164 
165 	if (found)
166 		*found = false;
167 
168 	return false;
169 }
170 
getUniformTextureFromTag(QDomElement & root,QString tag,bool * found)171 bool UniformVar::getUniformTextureFromTag(QDomElement & root, QString tag, bool * found)
172 {
173 	QDomElement el = RmXmlParser::getDomElement(root, tag, textureName);
174 
175 	if (!el.isNull()) {
176 		if (found)
177 			*found = true;
178 		representerTagName = tag;
179 		textureFilename = el.attribute("FILE_NAME");
180 		return true;
181 	}
182 
183 	if (found)
184 		*found = false;
185 
186 	return false;
187 }
188 
189 
getValueFromXmlDocument(QDomElement & root,bool echoNotFound)190 bool UniformVar::getValueFromXmlDocument(QDomElement &root, bool echoNotFound)
191 {
192 	bool fnd;
193 	bool ok;
194 
195 	switch (type) {
196 	case BOOL:
197 		ok = getUniformBooleanVectorFromTag(root, "RmBooleanVariable", 1, &bvalue, &fnd);
198 		if (fnd)
199 			return ok;
200 		break;
201 
202 	case INT:
203 		ok = getUniformNumberVectorFromTag(root, "RmIntegerVariable", 1, &ivalue, &fnd);
204 		if (fnd)
205 			return ok;
206 		break;
207 
208 	case FLOAT:
209 		ok = getUniformNumberVectorFromTag(root, "RmFloatVariable", 1, &fvalue, &fnd);
210 		if (fnd)
211 			return ok;
212 		break;
213 
214 	case IVEC2:
215 		ok = getUniformNumberVectorFromTag(root, "RmVectorVariable", 2, ivec2, &fnd);
216 		if (fnd)
217 			return ok;
218 		break;
219 
220 	case IVEC3:
221 		ok = getUniformNumberVectorFromTag(root, "RmVectorVariable", 3, ivec3, &fnd);
222 		if (fnd)
223 			return ok;
224 		break;
225 
226 	case IVEC4:
227 		ok = getUniformNumberVectorFromTag(root, "RmVectorVariable", 4, ivec4, &fnd);
228 		if (fnd)
229 			return ok;
230 		break;
231 
232 	case BVEC2:
233 		ok = getUniformBooleanVectorFromTag(root, "RmVectorVariable", 2, bvec2, &fnd);
234 		if (fnd)
235 			return ok;
236 		break;
237 
238 	case BVEC3:
239 		ok = getUniformBooleanVectorFromTag(root, "RmVectorVariable", 3, bvec3, &fnd);
240 		if (fnd)
241 			return ok;
242 		break;
243 
244 	case BVEC4:
245 		ok = getUniformBooleanVectorFromTag(root, "RmVectorVariable", 4, bvec4, &fnd);
246 		if (fnd)
247 			return ok;
248 		break;
249 
250 	case VEC2:
251 		ok = getUniformNumberVectorFromTag(root, "RmVectorVariable", 2, vec2, &fnd);
252 		if (fnd)
253 			return ok;
254 		break;
255 
256 	case VEC3:
257 		ok = getUniformNumberVectorFromTag(root, "RmVectorVariable", 3, vec3, &fnd);
258 		if (fnd)
259 			return ok;
260 		break;
261 
262 	case VEC4:
263 		// * a vec4 can be RmVectorVariable or RmColorVariable
264 		ok = getUniformNumberVectorFromTag(root, "RmVectorVariable", 4, vec4, &fnd);
265 		if (fnd)
266 			return ok;
267 
268 		ok = getUniformNumberVectorFromTag(root, "RmColorVariable", 4, vec4, &fnd);
269 		if (fnd)
270 			return ok;
271 		break;
272 
273 	case MAT2:
274 		ok = getUniformNumberVectorFromTag(root, "RmMatrixVariable", 4, (float*)mat2, &fnd);
275 		if (fnd)
276 			return ok;
277 		break;
278 
279 	case MAT3:
280 		ok = getUniformNumberVectorFromTag(root, "RmMatrixVariable", 8, (float*)mat3, &fnd);
281 		if (fnd)
282 			return ok;
283 		break;
284 
285 	case MAT4:
286 		ok = getUniformNumberVectorFromTag(root, "RmMatrixVariable", 16, (float*)mat4, &fnd);
287 		if (fnd)
288 			return ok;
289 		break;
290 
291 	case SAMPLER2D:
292 		// * sampler 2d can be Rm2DTextureVariable or not come from a texture file but
293 		// * found in a RmRenderTarget xml tag
294 		ok = getUniformTextureFromTag(root, "Rm2DTextureVariable", &fnd);
295 		if (fnd)
296 			return ok;
297 
298 		if (getUniformKnownButUnimplementedTag(root, "RmRenderTarget", textureName))
299 			return true;
300 		break;
301 
302 	case SAMPLER3D:
303 		ok = getUniformTextureFromTag(root, "Rm3DTextureVariable", &fnd);
304 		if (fnd)
305 			return ok;
306 		break;
307 
308 	case SAMPLERCUBE:
309 		ok = getUniformTextureFromTag(root, "RmCubemapVariable", &fnd);
310 		if (fnd)
311 			return ok;
312 		break;
313 
314 	default:
315 		qDebug() << "RmXmlParser for uniform variable" << name << "of type"
316 		         << UniformVar::getStringFromUniformType(type);
317 		qDebug() << "I don't know how to read my default value.. please implement me !";
318 		return false;
319 	}
320 
321 	// * any variable can be defined as RmDynamicVariable
322 	if (getUniformKnownButUnimplementedTag( root, "RmDynamicVariable", name))
323 		return true;
324 
325 	if (echoNotFound) {
326 		qDebug() << "RmXmlParser for uniform variable" << name << "of type"
327 		         << UniformVar::getStringFromUniformType(type);
328 		qDebug() << "Default value not found";
329 	}
330 	return false;
331 }
332 
333 QString UniformVar::typeList[NUM_TYPES] = {
334 	"int", "float", "bool",
335 	"vec2", "vec3", "vec4",
336 	"ivec2", "ivec3", "ivec4",
337 	"bvec2", "bvec3", "bvec4",
338 	"mat2", "mat3", "mat4",
339 	"sampler1D", "sampler2D", "sampler3D",
340 	"samplerCube",
341 	"sampler1Dshadow", "sampler2Dshadow"
342 };
343 
getTypeFromString(QString & type)344 enum UniformVar::UniformType UniformVar::getTypeFromString(QString &type)
345 {
346 	for (int i = 0; i < 21; i++)
347 		if (type == typeList[i])
348 			return static_cast<UniformType>(i);
349 	return OTHER;
350 }
351 
352 
getStringFromUniformType(UniformType type)353 QString UniformVar::getStringFromUniformType(UniformType type)
354 {
355 	if (!(type < INT && type > SAMPLER2DSHADOW))
356 		return typeList[type];
357 	return "other";
358 }
359 
VarDump(int indent,bool extendedVarDump)360 void UniformVar::VarDump(int indent, bool extendedVarDump)
361 {
362 	QString ret = "";
363 
364 	for (int i = 0; i < indent; i++)
365 		ret += " ";
366 
367 	ret += typeString + QString(" ") + name;
368 
369 	switch (type) {
370 	case INT:
371 		ret += " = " + QString().setNum(ivalue);
372 		if (minSet || maxSet)
373 			ret += " (";
374 		if (minSet)
375 			ret += "from " + QString().setNum(imin) + " ";
376 		if (maxSet)
377 			ret += "to "+ QString().setNum(imax);
378 		if (minSet || maxSet)
379 			ret += ")";
380 		break;
381 
382 	case FLOAT:
383 		ret += " = " + QString().setNum(fvalue);
384 		if (minSet || maxSet)
385 			ret += " (";
386 		if (minSet)
387 			ret += "from " + QString().setNum(fmin) + " ";
388 		if (maxSet)
389 			ret += "to "+ QString().setNum(fmax);
390 		if (minSet || maxSet)
391 			ret += ")";
392 		break;
393 
394 	case BOOL:
395 		ret += bvalue ? " = true" : " = false";
396 		break;
397 
398 	case IVEC2:
399 		ret += " = [ ";
400 		for (int i = 0; i < 2; i++)
401 			ret += QString().setNum(ivec2[i]) + " ";
402 		ret += "]";
403 		break;
404 
405 	case IVEC3:
406 		ret += " = [ ";
407 		for (int i = 0; i < 3; i++)
408 			ret += QString().setNum(ivec3[i]) + " ";
409 		ret += "]";
410 		break;
411 
412 	case IVEC4:
413 		ret += " = [ ";
414 		for (int i = 0; i < 4; i++)
415 			ret += QString().setNum(ivec4[i]) + " ";
416 		ret += "]";
417 		break;
418 
419 	case BVEC2:
420 		ret += " = [ ";
421 		for (int i = 0; i < 2; i++)
422 			ret += bvec2[i] ? "true " : "false ";
423 		ret += "]";
424 		break;
425 
426 	case BVEC3:
427 		ret += " = [ ";
428 		for (int i = 0; i < 3; i++)
429 			ret += bvec3[i] ? "true " : "false ";
430 		ret += "]";
431 		break;
432 
433 	case BVEC4:
434 		ret += " = [ ";
435 		for (int i = 0; i < 4; i++)
436 			ret += bvec4[i] ? "true " : "false ";
437 		ret += "]";
438 		break;
439 
440 	case VEC2:
441 		ret += " = [ ";
442 		for (int i = 0; i < 2; i++)
443 			ret += QString().setNum(vec2[i]) + " ";
444 		ret += "]";
445 		break;
446 
447 	case VEC3:
448 		ret += " = [ ";
449 		for (int i = 0; i < 3; i++)
450 			ret += QString().setNum(vec3[i]) + " ";
451 		ret += "]";
452 		break;
453 
454 	case VEC4:
455 		ret += " = [ ";
456 		for (int i = 0; i < 4; i++)
457 			ret += QString().setNum(vec3[i]) + " ";
458 		ret += "]";
459 		break;
460 
461 	case MAT2:
462 	case MAT3:
463 	case MAT4:
464 		ret += " [matrix]";
465 		if (extendedVarDump) {
466 			int n = ((type == MAT2)? 2 : ((type == MAT3)? 3 : 4));
467 			float *mat = ((type == MAT2)?
468 					(float*)mat2 :
469 					(type == MAT3)? (float*)mat3 : (float*)mat4);
470 			ret += "\n";
471 
472 			for (int i = 0; i < n; i++) {
473 				for (int k = 0; k < indent+2; k++)
474 					ret += " ";
475 				ret += "[ ";
476 
477 				for (int j = 0; j < n; j++)
478 					ret += QString().setNum( mat[i*n+j] ) + " ";
479 				ret += "]";
480 
481 				if (i + 1 < n)
482 					ret += "\n";
483 			}
484 		}
485 		break;
486 
487 	case SAMPLER1DSHADOW:
488 	case SAMPLER2DSHADOW:
489 	case SAMPLERCUBE:
490 	case SAMPLER1D:
491 	case SAMPLER2D:
492 	case SAMPLER3D:
493 		if (textureFilename.isEmpty())
494 			ret += " = no filename, textureName = " + textureName;
495 		else
496 			ret += " = " + textureFilename;
497 
498 		if (representerTagName == "RmRenderTarget")
499 			ret += " [RmRenderTarget]";
500 
501 		if (extendedVarDump) {
502 			if (textureGLStates.size() == 0) {
503 				ret += " [with no openGL states]";
504 			} else {
505 				ret += "\n";
506 				for (int i = 0; i < textureGLStates.size(); i++) {
507 					for (int j = 0; j < indent+2; j++)
508 						ret += " ";
509 
510 					ret += "\""  + textureGLStates[i].getName() + "\" (" +
511 					       QString().setNum(textureGLStates[i].getState()).toLatin1().data() + ") => " +
512 					       QString().setNum(textureGLStates[i].getValue());
513 
514 					if (i + 1 < textureGLStates.size())
515 						ret += "\n";
516 				}
517 			}
518 		} else {
519 			ret += " [openGL states: " + QString().setNum(textureGLStates.size()) + "]";
520 		}
521 		break;
522 
523 	default:
524 		ret += " [implement me]";
525 	}
526 
527 	qDebug() << ret.toLatin1().data();
528 }
529 
530 
getUniformNumberVectorFromXmlTag(QDomElement & el,int values,void * narr,bool intOrFloat,UniformVar * ptr)531 bool UniformVar::getUniformNumberVectorFromXmlTag(QDomElement &el, int values, void *narr, bool intOrFloat, UniformVar *ptr)
532 {
533 	int *iarr = (int*)narr;
534 	float *farr = (float*)narr;
535 
536 	bool ok1 = true, ok2 = true;
537 
538 	for (int i = 0; i < values; i++) {
539 		QString attrname = "VALUE";
540 		if (values > 1)
541 			attrname += "_" + QString().setNum(i);
542 		QString attrvalue = el.attribute(attrname);
543 
544 		if (intOrFloat) {
545 			int val = attrvalue.toInt(&ok1);
546 			if (ok1) {
547 				iarr[i] = val;
548 				ptr->testRealMin(val);
549 				ptr->testRealMax(val);
550 			}
551 		} else {
552 			float val = attrvalue.toFloat(&ok1);
553 			if (ok1) {
554 				farr[i] = val;
555 				ptr->testRealMin(val);
556 				ptr->testRealMax(val);
557 			}
558 		}
559 
560 		if (!ok1) {
561 			qDebug() << "RmXmlParser: error while reading default value for "
562 			         << (intOrFloat ? "int" : "float" ) << " vector["
563 			         << values << "]" << el.attribute("NAME") << ":"
564 			         << attrname << "=>" << attrvalue;
565 			return false;
566 		}
567 	}
568 
569 	if (!el.attribute("MIN").isEmpty()) {
570 		if (intOrFloat)	{
571 			int min = el.attribute("MIN").toInt(&ok1);
572 			if (ok1)
573 				ptr->setMin(min);
574 		} else {
575 			float min = el.attribute("MIN").toFloat(&ok1);
576 			if (ok1)
577 				ptr->setMin(min);
578 		}
579 	}
580 
581 	if (!el.attribute("MAX").isEmpty()) {
582 		if (intOrFloat)	{
583 			int max = el.attribute("MAX").toInt(&ok2);
584 			if (ok2)
585 				ptr->setMax(max);
586 		} else {
587 			float max = el.attribute("MAX").toFloat(&ok2);
588 			if (ok2)
589 				ptr->setMax(max);
590 		}
591 	}
592 
593 	if (!ok1 || !ok2) {
594 		qDebug() << "RmXmlParser: error while reading default value for float vector["
595 		         << values << "]" << el.attribute("NAME");
596 		qDebug() << "Min_ok("<< ok1 <<") Max_ok("<< ok2 <<")";
597 	}
598 
599 	return true;
600 }
601 
getUniformBooleanVectorFromXmlTag(QDomElement & el,int values,bool * barr)602 bool UniformVar::getUniformBooleanVectorFromXmlTag(QDomElement &el, int values, bool *barr)
603 {
604 	for (int i = 0; i < values; i++) {
605 		QString attrname = "VALUE";
606 		if (values > 1)
607 			attrname += "_" + QString().setNum(i);
608 
609 		QString attrvalue = el.attribute(attrname);
610 
611 		if (attrvalue != "TRUE" && attrvalue != "FALSE") {
612 			qDebug() << "RmXmlParser: error while reading default value for boolean vector["
613 			         << values<<"]" << el.attribute("NAME");
614 			qDebug() << attrvalue << "is not TRUE neither FALSE";
615 			return false;
616 		}
617 		barr[i] = (attrvalue == "TRUE");
618 	}
619 	return true;
620 }
621