Home | History | Annotate | Download | only in scripts
      1 # -*- coding: utf-8 -*-
      2 
      3 #-------------------------------------------------------------------------
      4 # drawElements Quality Program utilities
      5 # --------------------------------------
      6 #
      7 # Copyright 2016 The Android Open Source Project
      8 #
      9 # Licensed under the Apache License, Version 2.0 (the "License");
     10 # you may not use this file except in compliance with the License.
     11 # You may obtain a copy of the License at
     12 #
     13 #      http://www.apache.org/licenses/LICENSE-2.0
     14 #
     15 # Unless required by applicable law or agreed to in writing, software
     16 # distributed under the License is distributed on an "AS IS" BASIS,
     17 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18 # See the License for the specific language governing permissions and
     19 # limitations under the License.
     20 #
     21 #-------------------------------------------------------------------------
     22 
     23 import re
     24 import math
     25 import random
     26 
     27 PREAMBLE = """
     28 # WARNING: This file is auto-generated. Do NOT modify it manually, but rather
     29 # modify the generating script file. Otherwise changes will be lost!
     30 """[1:]
     31 
     32 class CaseGroup(object):
     33 	def __init__(self, name, description, children):
     34 		self.name			= name
     35 		self.description	= description
     36 		self.children		= children
     37 
     38 class ShaderCase(object):
     39 	def __init__(self):
     40 		pass
     41 
     42 g_processedCases = {}
     43 
     44 def indentTextBlock(text, indent):
     45 	indentStr = indent * "\t"
     46 	lines = text.split("\n")
     47 	lines = [indentStr + line for line in lines]
     48 	lines = [ ["", line][line.strip() != ""] for line in lines]
     49 	return "\n".join(lines)
     50 
     51 def writeCase(f, case, indent, prefix):
     52 	print "    %s" % (prefix + case.name)
     53 	if isinstance(case, CaseGroup):
     54 		f.write(indentTextBlock('group %s "%s"\n\n' % (case.name, case.description), indent))
     55 		for child in case.children:
     56 			writeCase(f, child, indent + 1, prefix + case.name + ".")
     57 		f.write(indentTextBlock("\nend # %s\n" % case.name, indent))
     58 	else:
     59 		# \todo [petri] Fix hack.
     60 		fullPath = prefix + case.name
     61 		assert (fullPath not in g_processedCases)
     62 		g_processedCases[fullPath] = None
     63 		f.write(indentTextBlock(str(case) + "\n", indent))
     64 
     65 def writeAllCases(fileName, caseList):
     66 	# Write all cases to file.
     67 	print "  %s.." % fileName
     68 	f = file(fileName, "wb")
     69 	f.write(PREAMBLE + "\n")
     70 	for case in caseList:
     71 		writeCase(f, case, 0, "")
     72 	f.close()
     73 
     74 	print "done! (%d cases written)" % len(g_processedCases)
     75 
     76 # Template operations.
     77 
     78 def genValues(inputs, outputs):
     79 	res = []
     80 	for (name, values) in inputs:
     81 		res.append("input %s = [ %s ];" % (name, " | ".join([str(v) for v in values]).lower()))
     82 	for (name, values) in outputs:
     83 		res.append("output %s = [ %s ];" % (name, " | ".join([str(v) for v in values]).lower()))
     84 	return ("\n".join(res))
     85 
     86 def fillTemplate(template, params):
     87 	s = template
     88 
     89 	for (key, value) in params.items():
     90 		m = re.search(r"^(\s*)\$\{\{%s\}\}$" % key, s, re.M)
     91 		if m is not None:
     92 			start = m.start(0)
     93 			end = m.end(0)
     94 			ws = m.group(1)
     95 			if value is not None:
     96 				repl = "\n".join(["%s%s" % (ws, line) for line in value.split("\n")])
     97 				s = s[:start] + repl + s[end:]
     98 			else:
     99 				s = s[:start] + s[end+1:] # drop the whole line
    100 		else:
    101 			s = s.replace("${{%s}}" % key, value)
    102 	return s
    103 
    104 # Return shuffled version of list
    105 def shuffled(lst):
    106 	tmp = lst[:]
    107 	random.shuffle(tmp)
    108 	return tmp
    109 
    110 def repeatToLength(lst, toLength):
    111 	return (toLength / len(lst)) * lst + lst[: toLength % len(lst)]
    112 
    113 # Helpers to convert a list of Scalar/Vec values into another type.
    114 
    115 def toFloat(lst):	return [Scalar(float(v.x)) for v in lst]
    116 def toInt(lst):		return [Scalar(int(v.x)) for v in lst]
    117 def toUint(lst):	return [Uint(int(v.x)) for v in lst]
    118 def toBool(lst):	return [Scalar(bool(v.x)) for v in lst]
    119 def toVec4(lst):	return [v.toFloat().toVec4() for v in lst]
    120 def toVec3(lst):	return [v.toFloat().toVec3() for v in lst]
    121 def toVec2(lst):	return [v.toFloat().toVec2() for v in lst]
    122 def toIVec4(lst):	return [v.toInt().toVec4() for v in lst]
    123 def toIVec3(lst):	return [v.toInt().toVec3() for v in lst]
    124 def toIVec2(lst):	return [v.toInt().toVec2() for v in lst]
    125 def toBVec4(lst):	return [v.toBool().toVec4() for v in lst]
    126 def toBVec3(lst):	return [v.toBool().toVec3() for v in lst]
    127 def toBVec2(lst):	return [v.toBool().toVec2() for v in lst]
    128 def toUVec4(lst):	return [v.toUint().toUVec4() for v in lst]
    129 def toUVec3(lst):	return [v.toUint().toUVec3() for v in lst]
    130 def toUVec2(lst):	return [v.toUint().toUVec2() for v in lst]
    131 def toMat2(lst):	return [v.toMat2() for v in lst]
    132 def toMat2x3(lst):	return [v.toMat2x3() for v in lst]
    133 def toMat2x4(lst):	return [v.toMat2x4() for v in lst]
    134 def toMat3x2(lst):	return [v.toMat3x2() for v in lst]
    135 def toMat3(lst):	return [v.toMat3() for v in lst]
    136 def toMat3x4(lst):	return [v.toMat3x4() for v in lst]
    137 def toMat4x2(lst):	return [v.toMat4x2() for v in lst]
    138 def toMat4x3(lst):	return [v.toMat4x3() for v in lst]
    139 def toMat4(lst):	return [v.toMat4() for v in lst]
    140 
    141 # Random value generation.
    142 
    143 class GenRandom(object):
    144 	def __init__(self):
    145 		pass
    146 
    147 	def uniformVec4(self, count, mn, mx):
    148 		ret = [Vec4(random.uniform(mn, mx), random.uniform(mn, mx), random.uniform(mn, mx), random.uniform(mn, mx)) for x in xrange(count)]
    149 		ret[0].x = mn
    150 		ret[1].x = mx
    151 		ret[2].x = (mn + mx) * 0.5
    152 		return ret
    153 
    154 	def uniformBVec4(self, count):
    155 		ret = [Vec4(random.random() >= 0.5, random.random() >= 0.5, random.random() >= 0.5, random.random() >= 0.5) for x in xrange(count)]
    156 		ret[0].x = True
    157 		ret[1].x = False
    158 		return ret
    159 
    160 #	def uniform(self,
    161 
    162 # Math operating on Scalar/Vector types.
    163 
    164 def glslSign(a):			return 0.0 if (a == 0) else +1.0 if (a > 0.0) else -1.0
    165 def glslMod(x, y):			return x - y*math.floor(x/y)
    166 def glslClamp(x, mn, mx):	return mn if (x < mn) else mx if (x > mx) else x
    167 
    168 class GenMath(object):
    169 	@staticmethod
    170 	def unary(func):	return lambda val: val.applyUnary(func)
    171 
    172 	@staticmethod
    173 	def binary(func):	return lambda a, b: (b.expandVec(a)).applyBinary(func, a.expandVec(b))
    174 
    175 	@staticmethod
    176 	def frac(val):		return val.applyUnary(lambda x: x - math.floor(x))
    177 
    178 	@staticmethod
    179 	def exp2(val):		return val.applyUnary(lambda x: math.pow(2.0, x))
    180 
    181 	@staticmethod
    182 	def log2(val):		return val.applyUnary(lambda x: math.log(x, 2.0))
    183 
    184 	@staticmethod
    185 	def rsq(val):		return val.applyUnary(lambda x: 1.0 / math.sqrt(x))
    186 
    187 	@staticmethod
    188 	def sign(val):		return val.applyUnary(glslSign)
    189 
    190 	@staticmethod
    191 	def isEqual(a, b):	return Scalar(a.isEqual(b))
    192 
    193 	@staticmethod
    194 	def isNotEqual(a, b):	return Scalar(not a.isEqual(b))
    195 
    196 	@staticmethod
    197 	def step(a, b):		return (b.expandVec(a)).applyBinary(lambda edge, x: [1.0, 0.0][x < edge], a.expandVec(b))
    198 
    199 	@staticmethod
    200 	def length(a):		return a.length()
    201 
    202 	@staticmethod
    203 	def distance(a, b):	return a.distance(b)
    204 
    205 	@staticmethod
    206 	def dot(a, b):		return a.dot(b)
    207 
    208 	@staticmethod
    209 	def cross(a, b):	return a.cross(b)
    210 
    211 	@staticmethod
    212 	def normalize(a):	return a.normalize()
    213 
    214 	@staticmethod
    215 	def boolAny(a):		return a.boolAny()
    216 
    217 	@staticmethod
    218 	def boolAll(a):		return a.boolAll()
    219 
    220 	@staticmethod
    221 	def boolNot(a):		return a.boolNot()
    222 
    223 	@staticmethod
    224 	def abs(a):			return a.abs()
    225 
    226 # ..
    227 
    228 class Scalar(object):
    229 	def __init__(self, x):
    230 		self.x = x
    231 
    232 	def applyUnary(self, func):			return Scalar(func(self.x))
    233 	def applyBinary(self, func, other):	return Scalar(func(self.x, other.x))
    234 
    235 	def isEqual(self, other):	assert isinstance(other, Scalar); return (self.x == other.x)
    236 
    237 	def expandVec(self, val):	return val
    238 	def toScalar(self):			return Scalar(self.x)
    239 	def toVec2(self):			return Vec2(self.x, self.x)
    240 	def toVec3(self):			return Vec3(self.x, self.x, self.x)
    241 	def toVec4(self):			return Vec4(self.x, self.x, self.x, self.x)
    242 	def toUVec2(self):			return UVec2(self.x, self.x)
    243 	def toUVec3(self):			return UVec3(self.x, self.x, self.x)
    244 	def toUVec4(self):			return UVec4(self.x, self.x, self.x, self.x)
    245 	def toMat2(self):			return Mat.fromScalar(2, 2, float(self.x))
    246 	def toMat2x3(self):			return Mat.fromScalar(2, 3, float(self.x))
    247 	def toMat2x4(self):			return Mat.fromScalar(2, 4, float(self.x))
    248 	def toMat3x2(self):			return Mat.fromScalar(3, 2, float(self.x))
    249 	def toMat3(self):			return Mat.fromScalar(3, 3, float(self.x))
    250 	def toMat3x4(self):			return Mat.fromScalar(3, 4, float(self.x))
    251 	def toMat4x2(self):			return Mat.fromScalar(4, 2, float(self.x))
    252 	def toMat4x3(self):			return Mat.fromScalar(4, 3, float(self.x))
    253 	def toMat4(self):			return Mat.fromScalar(4, 4, float(self.x))
    254 
    255 	def toFloat(self):			return Scalar(float(self.x))
    256 	def toInt(self):			return Scalar(int(self.x))
    257 	def toUint(self):			return Uint(int(self.x))
    258 	def toBool(self):			return Scalar(bool(self.x))
    259 
    260 	def getNumScalars(self):	return 1
    261 	def getScalars(self):		return [self.x]
    262 
    263 	def typeString(self):
    264 		if isinstance(self.x, bool):
    265 			return "bool"
    266 		elif isinstance(self.x, int):
    267 			return "int"
    268 		elif isinstance(self.x, float):
    269 			return "float"
    270 		else:
    271 			assert False
    272 
    273 	def vec4Swizzle(self):
    274 		return ""
    275 
    276 	def __str__(self):
    277 		return str(self.x).lower()
    278 
    279 	def __float__(self):
    280 		return float(self.x)
    281 
    282 	def length(self):
    283 		return Scalar(abs(self.x))
    284 
    285 	def distance(self, v):
    286 		assert isinstance(v, Scalar)
    287 		return Scalar(abs(self.x - v.x))
    288 
    289 	def dot(self, v):
    290 		assert isinstance(v, Scalar)
    291 		return Scalar(self.x * v.x)
    292 
    293 	def normalize(self):
    294 		return Scalar(glslSign(self.x))
    295 
    296 	def abs(self):
    297 		if isinstance(self.x, bool):
    298 			return Scalar(self.x)
    299 		else:
    300 			return Scalar(abs(self.x))
    301 
    302 	def __neg__(self):
    303 		return Scalar(-self.x)
    304 
    305 	def __add__(self, val):
    306 		assert isinstance(val, Scalar)
    307 		return Scalar(self.x + val.x)
    308 
    309 	def __sub__(self, val):
    310 		return self + (-val)
    311 
    312 	def __mul__(self, val):
    313 		if isinstance(val, Scalar):
    314 			return Scalar(self.x * val.x)
    315 		elif isinstance(val, Vec2):
    316 			return Vec2(self.x * val.x, self.x * val.y)
    317 		elif isinstance(val, Vec3):
    318 			return Vec3(self.x * val.x, self.x * val.y, self.x * val.z)
    319 		elif isinstance(val, Vec4):
    320 			return Vec4(self.x * val.x, self.x * val.y, self.x * val.z, self.x * val.w)
    321 		else:
    322 			assert False
    323 
    324 	def __div__(self, val):
    325 		if isinstance(val, Scalar):
    326 			return Scalar(self.x / val.x)
    327 		elif isinstance(val, Vec2):
    328 			return Vec2(self.x / val.x, self.x / val.y)
    329 		elif isinstance(val, Vec3):
    330 			return Vec3(self.x / val.x, self.x / val.y, self.x / val.z)
    331 		elif isinstance(val, Vec4):
    332 			return Vec4(self.x / val.x, self.x / val.y, self.x / val.z, self.x / val.w)
    333 		else:
    334 			assert False
    335 
    336 class Uint(Scalar):
    337 	def __init__(self, x):
    338 		assert x >= 0
    339 		self.x = x
    340 
    341 	def typeString(self):
    342 		return "uint"
    343 
    344 	def abs(self):
    345 		return Scalar.abs(self).toUint()
    346 
    347 	def __neg__(self):
    348 		return Scalar.__neg__(self).toUint()
    349 
    350 	def __add__(self, val):
    351 		return Scalar.__add__(self, val).toUint()
    352 
    353 	def __sub__(self, val):
    354 		return self + (-val)
    355 
    356 	def __mul__(self, val):
    357 		return Scalar.__mul__(self, val).toUint()
    358 
    359 	def __div__(self, val):
    360 		return Scalar.__div__(self, val).toUint()
    361 
    362 class Vec(object):
    363 	@staticmethod
    364 	def fromScalarList(lst):
    365 		assert (len(lst) >= 1 and len(lst) <= 4)
    366 		if (len(lst) == 1):		return Scalar(lst[0])
    367 		elif (len(lst) == 2):	return Vec2(lst[0], lst[1])
    368 		elif (len(lst) == 3):	return Vec3(lst[0], lst[1], lst[2])
    369 		else:					return Vec4(lst[0], lst[1], lst[2], lst[3])
    370 
    371 	def isEqual(self, other):
    372 		assert isinstance(other, Vec);
    373 		return (self.getScalars() == other.getScalars())
    374 
    375 	def length(self):
    376 		return Scalar(math.sqrt(self.dot(self).x))
    377 
    378 	def normalize(self):
    379 		return self * Scalar(1.0 / self.length().x)
    380 
    381 	def swizzle(self, indexList):
    382 		inScalars = self.getScalars()
    383 		outScalars = map(lambda ndx: inScalars[ndx], indexList)
    384 		return Vec.fromScalarList(outScalars)
    385 
    386 	def __init__(self):
    387 		pass
    388 
    389 	def __eq__(self, other):
    390 		return self.isEqual(other)
    391 
    392 	def __ne__(self, other):
    393 		return not self.isEqual(other)
    394 
    395 class Vec2(Vec):
    396 	def __init__(self, x, y):
    397 		assert(x.__class__ == y.__class__)
    398 		self.x = x
    399 		self.y = y
    400 
    401 	def applyUnary(self, func):			return Vec2(func(self.x), func(self.y))
    402 	def applyBinary(self, func, other):	return Vec2(func(self.x, other.x), func(self.y, other.y))
    403 
    404 	def expandVec(self, val):	return val.toVec2()
    405 	def toScalar(self):			return Scalar(self.x)
    406 	def toVec2(self):			return Vec2(self.x, self.y)
    407 	def toVec3(self):			return Vec3(self.x, self.y, 0.0)
    408 	def toVec4(self):			return Vec4(self.x, self.y, 0.0, 0.0)
    409 	def toUVec2(self):			return UVec2(self.x, self.y)
    410 	def toUVec3(self):			return UVec3(self.x, self.y, 0.0)
    411 	def toUVec4(self):			return UVec4(self.x, self.y, 0.0, 0.0)
    412 	def toMat2(self):			return Mat2(float(self.x), 0.0, 0.0, float(self.y));
    413 
    414 	def toFloat(self):			return Vec2(float(self.x), float(self.y))
    415 	def toInt(self):			return Vec2(int(self.x), int(self.y))
    416 	def toUint(self):			return UVec2(int(self.x), int(self.y))
    417 	def toBool(self):			return Vec2(bool(self.x), bool(self.y))
    418 
    419 	def getNumScalars(self):	return 2
    420 	def getScalars(self):		return [self.x, self.y]
    421 
    422 	def typeString(self):
    423 		if isinstance(self.x, bool):
    424 			return "bvec2"
    425 		elif isinstance(self.x, int):
    426 			return "ivec2"
    427 		elif isinstance(self.x, float):
    428 			return "vec2"
    429 		else:
    430 			assert False
    431 
    432 	def vec4Swizzle(self):
    433 		return ".xyxy"
    434 
    435 	def __str__(self):
    436 		if isinstance(self.x, bool):
    437 			return "bvec2(%s, %s)" % (str(self.x).lower(), str(self.y).lower())
    438 		elif isinstance(self.x, int):
    439 			return "ivec2(%i, %i)" % (self.x, self.y)
    440 		elif isinstance(self.x, float):
    441 			return "vec2(%s, %s)" % (self.x, self.y)
    442 		else:
    443 			assert False
    444 
    445 	def distance(self, v):
    446 		assert isinstance(v, Vec2)
    447 		return (self - v).length()
    448 
    449 	def dot(self, v):
    450 		assert isinstance(v, Vec2)
    451 		return Scalar(self.x*v.x + self.y*v.y)
    452 
    453 	def abs(self):
    454 		if isinstance(self.x, bool):
    455 			return Vec2(self.x, self.y)
    456 		else:
    457 			return Vec2(abs(self.x), abs(self.y))
    458 
    459 	def __neg__(self):
    460 		return Vec2(-self.x, -self.y)
    461 
    462 	def __add__(self, val):
    463 		if isinstance(val, Scalar):
    464 			return Vec2(self.x + val, self.y + val)
    465 		elif isinstance(val, Vec2):
    466 			return Vec2(self.x + val.x, self.y + val.y)
    467 		else:
    468 			assert False
    469 
    470 	def __sub__(self, val):
    471 		return self + (-val)
    472 
    473 	def __mul__(self, val):
    474 		if isinstance(val, Scalar):
    475 			val = val.toVec2()
    476 		assert isinstance(val, Vec2)
    477 		return Vec2(self.x * val.x, self.y * val.y)
    478 
    479 	def __div__(self, val):
    480 		if isinstance(val, Scalar):
    481 			return Vec2(self.x / val.x, self.y / val.x)
    482 		else:
    483 			assert isinstance(val, Vec2)
    484 			return Vec2(self.x / val.x, self.y / val.y)
    485 
    486 	def boolAny(self):	return Scalar(self.x or self.y)
    487 	def boolAll(self):	return Scalar(self.x and self.y)
    488 	def boolNot(self):	return Vec2(not self.x, not self.y)
    489 
    490 class UVec2(Vec2):
    491 	def __init__(self, x, y):
    492 		assert isinstance(x, int) and isinstance(y, int)
    493 		assert x >= 0 and y >= 0
    494 		Vec2.__init__(self, x, y)
    495 
    496 	def typeString(self):
    497 		return "uvec2"
    498 
    499 	def __str__(self):
    500 		return "uvec2(%i, %i)" % (self.x, self.y)
    501 
    502 	def abs(self):
    503 		return Vec2.abs(self).toUint()
    504 
    505 class Vec3(Vec):
    506 	def __init__(self, x, y, z):
    507 		assert((x.__class__ == y.__class__) and (x.__class__ == z.__class__))
    508 		self.x = x
    509 		self.y = y
    510 		self.z = z
    511 
    512 	def applyUnary(self, func):			return Vec3(func(self.x), func(self.y), func(self.z))
    513 	def applyBinary(self, func, other):	return Vec3(func(self.x, other.x), func(self.y, other.y), func(self.z, other.z))
    514 
    515 	def expandVec(self, val):	return val.toVec3()
    516 	def toScalar(self):			return Scalar(self.x)
    517 	def toVec2(self):			return Vec2(self.x, self.y)
    518 	def toVec3(self):			return Vec3(self.x, self.y, self.z)
    519 	def toVec4(self):			return Vec4(self.x, self.y, self.z, 0.0)
    520 	def toUVec2(self):			return UVec2(self.x, self.y)
    521 	def toUVec3(self):			return UVec3(self.x, self.y, self.z)
    522 	def toUVec4(self):			return UVec4(self.x, self.y, self.z, 0.0)
    523 	def toMat3(self):			return Mat3(float(self.x), 0.0, 0.0,  0.0, float(self.y), 0.0,  0.0, 0.0, float(self.z));
    524 
    525 	def toFloat(self):			return Vec3(float(self.x), float(self.y), float(self.z))
    526 	def toInt(self):			return Vec3(int(self.x), int(self.y), int(self.z))
    527 	def toUint(self):			return UVec3(int(self.x), int(self.y), int(self.z))
    528 	def toBool(self):			return Vec3(bool(self.x), bool(self.y), bool(self.z))
    529 
    530 	def getNumScalars(self):	return 3
    531 	def getScalars(self):		return [self.x, self.y, self.z]
    532 
    533 	def typeString(self):
    534 		if isinstance(self.x, bool):
    535 			return "bvec3"
    536 		elif isinstance(self.x, int):
    537 			return "ivec3"
    538 		elif isinstance(self.x, float):
    539 			return "vec3"
    540 		else:
    541 			assert False
    542 
    543 	def vec4Swizzle(self):
    544 		return ".xyzx"
    545 
    546 	def __str__(self):
    547 		if isinstance(self.x, bool):
    548 			return "bvec3(%s, %s, %s)" % (str(self.x).lower(), str(self.y).lower(), str(self.z).lower())
    549 		elif isinstance(self.x, int):
    550 			return "ivec3(%i, %i, %i)" % (self.x, self.y, self.z)
    551 		elif isinstance(self.x, float):
    552 			return "vec3(%s, %s, %s)" % (self.x, self.y, self.z)
    553 		else:
    554 			assert False
    555 
    556 	def distance(self, v):
    557 		assert isinstance(v, Vec3)
    558 		return (self - v).length()
    559 
    560 	def dot(self, v):
    561 		assert isinstance(v, Vec3)
    562 		return Scalar(self.x*v.x + self.y*v.y + self.z*v.z)
    563 
    564 	def cross(self, v):
    565 		assert isinstance(v, Vec3)
    566 		return Vec3(self.y*v.z - v.y*self.z,
    567 					self.z*v.x - v.z*self.x,
    568 					self.x*v.y - v.x*self.y)
    569 
    570 	def abs(self):
    571 		if isinstance(self.x, bool):
    572 			return Vec3(self.x, self.y, self.z)
    573 		else:
    574 			return Vec3(abs(self.x), abs(self.y), abs(self.z))
    575 
    576 	def __neg__(self):
    577 		return Vec3(-self.x, -self.y, -self.z)
    578 
    579 	def __add__(self, val):
    580 		if isinstance(val, Scalar):
    581 			return Vec3(self.x + val, self.y + val)
    582 		elif isinstance(val, Vec3):
    583 			return Vec3(self.x + val.x, self.y + val.y, self.z + val.z)
    584 		else:
    585 			assert False
    586 
    587 	def __sub__(self, val):
    588 		return self + (-val)
    589 
    590 	def __mul__(self, val):
    591 		if isinstance(val, Scalar):
    592 			val = val.toVec3()
    593 		assert isinstance(val, Vec3)
    594 		return Vec3(self.x * val.x, self.y * val.y, self.z * val.z)
    595 
    596 	def __div__(self, val):
    597 		if isinstance(val, Scalar):
    598 			return Vec3(self.x / val.x, self.y / val.x, self.z / val.x)
    599 		elif isinstance(val, Vec3):
    600 			return Vec3(self.x / val.x, self.y / val.y, self.z / val.z)
    601 		else:
    602 			assert False
    603 
    604 	def boolAny(self):	return Scalar(self.x or self.y or self.z)
    605 	def boolAll(self):	return Scalar(self.x and self.y and self.z)
    606 	def boolNot(self):	return Vec3(not self.x, not self.y, not self.z)
    607 
    608 class UVec3(Vec3):
    609 	def __init__(self, x, y, z):
    610 		assert isinstance(x, int) and isinstance(y, int) and isinstance(z, int)
    611 		assert x >= 0 and y >= 0 and z >= 0
    612 		Vec3.__init__(self, x, y, z)
    613 
    614 	def typeString(self):
    615 		return "uvec3"
    616 
    617 	def __str__(self):
    618 		return "uvec3(%i, %i, %i)" % (self.x, self.y, self.z)
    619 
    620 	def abs(self):
    621 		return Vec3.abs(self).toUint()
    622 
    623 class Vec4(Vec):
    624 	def __init__(self, x, y, z, w):
    625 		assert((x.__class__ == y.__class__) and (x.__class__ == z.__class__) and (x.__class__ == w.__class__))
    626 		self.x = x
    627 		self.y = y
    628 		self.z = z
    629 		self.w = w
    630 
    631 	def applyUnary(self, func):			return Vec4(func(self.x), func(self.y), func(self.z), func(self.w))
    632 	def applyBinary(self, func, other):	return Vec4(func(self.x, other.x), func(self.y, other.y), func(self.z, other.z), func(self.w, other.w))
    633 
    634 	def expandVec(self, val):	return val.toVec4()
    635 	def toScalar(self):			return Scalar(self.x)
    636 	def toVec2(self):			return Vec2(self.x, self.y)
    637 	def toVec3(self):			return Vec3(self.x, self.y, self.z)
    638 	def toVec4(self):			return Vec4(self.x, self.y, self.z, self.w)
    639 	def toUVec2(self):			return UVec2(self.x, self.y)
    640 	def toUVec3(self):			return UVec3(self.x, self.y, self.z)
    641 	def toUVec4(self):			return UVec4(self.x, self.y, self.z, self.w)
    642 	def toMat2(self):			return Mat2(float(self.x), float(self.y), float(self.z), float(self.w))
    643 	def toMat4(self):			return Mat4(float(self.x), 0.0, 0.0, 0.0,  0.0, float(self.y), 0.0, 0.0,  0.0, 0.0, float(self.z), 0.0,  0.0, 0.0, 0.0, float(self.w));
    644 
    645 	def toFloat(self):			return Vec4(float(self.x), float(self.y), float(self.z), float(self.w))
    646 	def toInt(self):			return Vec4(int(self.x), int(self.y), int(self.z), int(self.w))
    647 	def toUint(self):			return UVec4(int(self.x), int(self.y), int(self.z), int(self.w))
    648 	def toBool(self):			return Vec4(bool(self.x), bool(self.y), bool(self.z), bool(self.w))
    649 
    650 	def getNumScalars(self):	return 4
    651 	def getScalars(self):		return [self.x, self.y, self.z, self.w]
    652 
    653 	def typeString(self):
    654 		if isinstance(self.x, bool):
    655 			return "bvec4"
    656 		elif isinstance(self.x, int):
    657 			return "ivec4"
    658 		elif isinstance(self.x, float):
    659 			return "vec4"
    660 		else:
    661 			assert False
    662 
    663 	def vec4Swizzle(self):
    664 		return ""
    665 
    666 	def __str__(self):
    667 		if isinstance(self.x, bool):
    668 			return "bvec4(%s, %s, %s, %s)" % (str(self.x).lower(), str(self.y).lower(), str(self.z).lower(), str(self.w).lower())
    669 		elif isinstance(self.x, int):
    670 			return "ivec4(%i, %i, %i, %i)" % (self.x, self.y, self.z, self.w)
    671 		elif isinstance(self.x, float):
    672 			return "vec4(%s, %s, %s, %s)" % (self.x, self.y, self.z, self.w)
    673 		else:
    674 			assert False
    675 
    676 	def distance(self, v):
    677 		assert isinstance(v, Vec4)
    678 		return (self - v).length()
    679 
    680 	def dot(self, v):
    681 		assert isinstance(v, Vec4)
    682 		return Scalar(self.x*v.x + self.y*v.y + self.z*v.z + self.w*v.w)
    683 
    684 	def abs(self):
    685 		if isinstance(self.x, bool):
    686 			return Vec4(self.x, self.y, self.z, self.w)
    687 		else:
    688 			return Vec4(abs(self.x), abs(self.y), abs(self.z), abs(self.w))
    689 
    690 	def __neg__(self):
    691 		return Vec4(-self.x, -self.y, -self.z, -self.w)
    692 
    693 	def __add__(self, val):
    694 		if isinstance(val, Scalar):
    695 			return Vec3(self.x + val, self.y + val)
    696 		elif isinstance(val, Vec4):
    697 			return Vec4(self.x + val.x, self.y + val.y, self.z + val.z, self.w + val.w)
    698 		else:
    699 			assert False
    700 
    701 	def __sub__(self, val):
    702 		return self + (-val)
    703 
    704 	def __mul__(self, val):
    705 		if isinstance(val, Scalar):
    706 			val = val.toVec4()
    707 		assert isinstance(val, Vec4)
    708 		return Vec4(self.x * val.x, self.y * val.y, self.z * val.z, self.w * val.w)
    709 
    710 	def __div__(self, val):
    711 		if isinstance(val, Scalar):
    712 			return Vec4(self.x / val.x, self.y / val.x, self.z / val.x, self.w / val.x)
    713 		elif isinstance(val, Vec4):
    714 			return Vec4(self.x / val.x, self.y / val.y, self.z / val.z, self.w / val.w)
    715 		else:
    716 			assert False
    717 
    718 	def boolAny(self):	return Scalar(self.x or self.y or self.z or self.w)
    719 	def boolAll(self):	return Scalar(self.x and self.y and self.z and self.w)
    720 	def boolNot(self):	return Vec4(not self.x, not self.y, not self.z, not self.w)
    721 
    722 class UVec4(Vec4):
    723 	def __init__(self, x, y, z, w):
    724 		assert isinstance(x, int) and isinstance(y, int) and isinstance(z, int) and isinstance(w, int)
    725 		assert x >= 0 and y >= 0 and z >= 0 and w >= 0
    726 		Vec4.__init__(self, x, y, z, w)
    727 
    728 	def typeString(self):
    729 		return "uvec4"
    730 
    731 	def __str__(self):
    732 		return "uvec4(%i, %i, %i, %i)" % (self.x, self.y, self.z, self.w)
    733 
    734 	def abs(self):
    735 		return Vec4.abs(self).toUint()
    736 
    737 # \note Column-major storage.
    738 class Mat(object):
    739 	def __init__ (self, numCols, numRows, scalars):
    740 		assert len(scalars) == numRows*numCols
    741 		self.numCols	= numCols
    742 		self.numRows	= numRows
    743 		self.scalars	= scalars
    744 
    745 	@staticmethod
    746 	def fromScalar (numCols, numRows, scalar):
    747 		scalars = []
    748 		for col in range(0, numCols):
    749 			for row in range(0, numRows):
    750 				scalars.append(scalar if col == row else 0.0)
    751 		return Mat(numCols, numRows, scalars)
    752 
    753 	@staticmethod
    754 	def identity (numCols, numRows):
    755 		return Mat.fromScalar(numCols, numRows, 1.0)
    756 
    757 	def get (self, colNdx, rowNdx):
    758 		assert 0 <= colNdx and colNdx < self.numCols
    759 		assert 0 <= rowNdx and rowNdx < self.numRows
    760 		return self.scalars[colNdx*self.numRows + rowNdx]
    761 
    762 	def set (self, colNdx, rowNdx, scalar):
    763 		assert 0 <= colNdx and colNdx < self.numCols
    764 		assert 0 <= rowNdx and rowNdx < self.numRows
    765 		self.scalars[colNdx*self.numRows + rowNdx] = scalar
    766 
    767 	def toMatrix (self, numCols, numRows):
    768 		res = Mat.identity(numCols, numRows)
    769 		for col in range(0, min(self.numCols, numCols)):
    770 			for row in range(0, min(self.numRows, numRows)):
    771 				res.set(col, row, self.get(col, row))
    772 		return res
    773 
    774 	def toMat2 (self):		return self.toMatrix(2, 2)
    775 	def toMat2x3 (self):	return self.toMatrix(2, 3)
    776 	def toMat2x4 (self):	return self.toMatrix(2, 4)
    777 	def toMat3x2 (self):	return self.toMatrix(3, 2)
    778 	def toMat3 (self):		return self.toMatrix(3, 3)
    779 	def toMat3x4 (self):	return self.toMatrix(3, 4)
    780 	def toMat4x2 (self):	return self.toMatrix(4, 2)
    781 	def toMat4x3 (self):	return self.toMatrix(4, 3)
    782 	def toMat4 (self):		return self.toMatrix(4, 4)
    783 
    784 	def typeString(self):
    785 		if self.numRows == self.numCols:
    786 			return "mat%d" % self.numRows
    787 		else:
    788 			return "mat%dx%d" % (self.numCols, self.numRows)
    789 
    790 	def __str__(self):
    791 		return "%s(%s)" % (self.typeString(), ", ".join(["%s" % s for s in self.scalars]))
    792 
    793 	def isTypeEqual (self, other):
    794 		return isinstance(other, Mat) and self.numRows == other.numRows and self.numCols == other.numCols
    795 
    796 	def isEqual(self, other):
    797 		assert self.isTypeEqual(other)
    798 		return (self.scalars == other.scalars)
    799 
    800 	def compMul(self, val):
    801 		assert self.isTypeEqual(val)
    802 		return Mat(self.numRows, self.numCols, [self.scalars(i) * val.scalars(i) for i in range(self.numRows*self.numCols)])
    803 
    804 class Mat2(Mat):
    805 	def __init__(self, m00, m01, m10, m11):
    806 		Mat.__init__(self, 2, 2, [m00, m10, m01, m11])
    807 
    808 class Mat3(Mat):
    809 	def __init__(self, m00, m01, m02, m10, m11, m12, m20, m21, m22):
    810 		Mat.__init__(self, 3, 3, [m00, m10, m20,
    811 								  m01, m11, m21,
    812 								  m02, m12, m22])
    813 
    814 class Mat4(Mat):
    815 	def __init__(self, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33):
    816 		Mat.__init__(self, 4, 4, [m00, m10, m20, m30,
    817 								  m01, m11, m21, m31,
    818 								  m02, m12, m22, m32,
    819 								  m03, m13, m23, m33])
    820