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 		if not isinstance(val, Scalar):
    307 			print val
    308 		assert isinstance(val, Scalar)
    309 		return Scalar(self.x + val.x)
    310 
    311 	def __sub__(self, val):
    312 		return self + (-val)
    313 
    314 	def __mul__(self, val):
    315 		if isinstance(val, Scalar):
    316 			return Scalar(self.x * val.x)
    317 		elif isinstance(val, Vec2):
    318 			return Vec2(self.x * val.x, self.x * val.y)
    319 		elif isinstance(val, Vec3):
    320 			return Vec3(self.x * val.x, self.x * val.y, self.x * val.z)
    321 		elif isinstance(val, Vec4):
    322 			return Vec4(self.x * val.x, self.x * val.y, self.x * val.z, self.x * val.w)
    323 		else:
    324 			assert False
    325 
    326 	def __div__(self, val):
    327 		if isinstance(val, Scalar):
    328 			return Scalar(self.x / val.x)
    329 		elif isinstance(val, Vec2):
    330 			return Vec2(self.x / val.x, self.x / val.y)
    331 		elif isinstance(val, Vec3):
    332 			return Vec3(self.x / val.x, self.x / val.y, self.x / val.z)
    333 		elif isinstance(val, Vec4):
    334 			return Vec4(self.x / val.x, self.x / val.y, self.x / val.z, self.x / val.w)
    335 		else:
    336 			assert False
    337 
    338 class Uint(Scalar):
    339 	def __init__(self, x):
    340 		assert x >= 0
    341 		self.x = x
    342 
    343 	def typeString(self):
    344 		return "uint"
    345 
    346 	def abs(self):
    347 		return Scalar.abs(self).toUint()
    348 
    349 	def __neg__(self):
    350 		return Scalar.__neg__(self).toUint()
    351 
    352 	def __add__(self, val):
    353 		return Scalar.__add__(self, val).toUint()
    354 
    355 	def __sub__(self, val):
    356 		return self + (-val)
    357 
    358 	def __mul__(self, val):
    359 		return Scalar.__mul__(self, val).toUint()
    360 
    361 	def __div__(self, val):
    362 		return Scalar.__div__(self, val).toUint()
    363 
    364 class Vec(object):
    365 	@staticmethod
    366 	def fromScalarList(lst):
    367 		assert (len(lst) >= 1 and len(lst) <= 4)
    368 		if (len(lst) == 1):		return Scalar(lst[0])
    369 		elif (len(lst) == 2):	return Vec2(lst[0], lst[1])
    370 		elif (len(lst) == 3):	return Vec3(lst[0], lst[1], lst[2])
    371 		else:					return Vec4(lst[0], lst[1], lst[2], lst[3])
    372 
    373 	def isEqual(self, other):
    374 		assert isinstance(other, Vec);
    375 		return (self.getScalars() == other.getScalars())
    376 
    377 	def length(self):
    378 		return Scalar(math.sqrt(self.dot(self).x))
    379 
    380 	def normalize(self):
    381 		return self * Scalar(1.0 / self.length().x)
    382 
    383 	def swizzle(self, indexList):
    384 		inScalars = self.getScalars()
    385 		outScalars = map(lambda ndx: inScalars[ndx], indexList)
    386 		return Vec.fromScalarList(outScalars)
    387 
    388 	def __init__(self):
    389 		pass
    390 
    391 	def __eq__(self, other):
    392 		return self.isEqual(other)
    393 
    394 	def __ne__(self, other):
    395 		return not self.isEqual(other)
    396 
    397 class Vec2(Vec):
    398 	def __init__(self, x, y):
    399 		assert(x.__class__ == y.__class__)
    400 		self.x = x
    401 		self.y = y
    402 
    403 	def applyUnary(self, func):			return Vec2(func(self.x), func(self.y))
    404 	def applyBinary(self, func, other):	return Vec2(func(self.x, other.x), func(self.y, other.y))
    405 
    406 	def expandVec(self, val):	return val.toVec2()
    407 	def toScalar(self):			return Scalar(self.x)
    408 	def toVec2(self):			return Vec2(self.x, self.y)
    409 	def toVec3(self):			return Vec3(self.x, self.y, 0.0)
    410 	def toVec4(self):			return Vec4(self.x, self.y, 0.0, 0.0)
    411 	def toUVec2(self):			return UVec2(self.x, self.y)
    412 	def toUVec3(self):			return UVec3(self.x, self.y, 0.0)
    413 	def toUVec4(self):			return UVec4(self.x, self.y, 0.0, 0.0)
    414 	def toMat2(self):			return Mat2(float(self.x), 0.0, 0.0, float(self.y));
    415 
    416 	def toFloat(self):			return Vec2(float(self.x), float(self.y))
    417 	def toInt(self):			return Vec2(int(self.x), int(self.y))
    418 	def toUint(self):			return UVec2(int(self.x), int(self.y))
    419 	def toBool(self):			return Vec2(bool(self.x), bool(self.y))
    420 
    421 	def getNumScalars(self):	return 2
    422 	def getScalars(self):		return [self.x, self.y]
    423 
    424 	def typeString(self):
    425 		if isinstance(self.x, bool):
    426 			return "bvec2"
    427 		elif isinstance(self.x, int):
    428 			return "ivec2"
    429 		elif isinstance(self.x, float):
    430 			return "vec2"
    431 		else:
    432 			assert False
    433 
    434 	def vec4Swizzle(self):
    435 		return ".xyxy"
    436 
    437 	def __str__(self):
    438 		if isinstance(self.x, bool):
    439 			return "bvec2(%s, %s)" % (str(self.x).lower(), str(self.y).lower())
    440 		elif isinstance(self.x, int):
    441 			return "ivec2(%i, %i)" % (self.x, self.y)
    442 		elif isinstance(self.x, float):
    443 			return "vec2(%s, %s)" % (self.x, self.y)
    444 		else:
    445 			assert False
    446 
    447 	def distance(self, v):
    448 		assert isinstance(v, Vec2)
    449 		return (self - v).length()
    450 
    451 	def dot(self, v):
    452 		assert isinstance(v, Vec2)
    453 		return Scalar(self.x*v.x + self.y*v.y)
    454 
    455 	def abs(self):
    456 		if isinstance(self.x, bool):
    457 			return Vec2(self.x, self.y)
    458 		else:
    459 			return Vec2(abs(self.x), abs(self.y))
    460 
    461 	def __neg__(self):
    462 		return Vec2(-self.x, -self.y)
    463 
    464 	def __add__(self, val):
    465 		if isinstance(val, Scalar):
    466 			return Vec2(self.x + val, self.y + val)
    467 		elif isinstance(val, Vec2):
    468 			return Vec2(self.x + val.x, self.y + val.y)
    469 		else:
    470 			assert False
    471 
    472 	def __sub__(self, val):
    473 		return self + (-val)
    474 
    475 	def __mul__(self, val):
    476 		if isinstance(val, Scalar):
    477 			val = val.toVec2()
    478 		assert isinstance(val, Vec2)
    479 		return Vec2(self.x * val.x, self.y * val.y)
    480 
    481 	def __div__(self, val):
    482 		if isinstance(val, Scalar):
    483 			return Vec2(self.x / val.x, self.y / val.x)
    484 		else:
    485 			assert isinstance(val, Vec2)
    486 			return Vec2(self.x / val.x, self.y / val.y)
    487 
    488 	def boolAny(self):	return Scalar(self.x or self.y)
    489 	def boolAll(self):	return Scalar(self.x and self.y)
    490 	def boolNot(self):	return Vec2(not self.x, not self.y)
    491 
    492 class UVec2(Vec2):
    493 	def __init__(self, x, y):
    494 		assert isinstance(x, int) and isinstance(y, int)
    495 		assert x >= 0 and y >= 0
    496 		Vec2.__init__(self, x, y)
    497 
    498 	def typeString(self):
    499 		return "uvec2"
    500 
    501 	def __str__(self):
    502 		return "uvec2(%i, %i)" % (self.x, self.y)
    503 
    504 	def abs(self):
    505 		return Vec2.abs(self).toUint()
    506 
    507 class Vec3(Vec):
    508 	def __init__(self, x, y, z):
    509 		assert((x.__class__ == y.__class__) and (x.__class__ == z.__class__))
    510 		self.x = x
    511 		self.y = y
    512 		self.z = z
    513 
    514 	def applyUnary(self, func):			return Vec3(func(self.x), func(self.y), func(self.z))
    515 	def applyBinary(self, func, other):	return Vec3(func(self.x, other.x), func(self.y, other.y), func(self.z, other.z))
    516 
    517 	def expandVec(self, val):	return val.toVec3()
    518 	def toScalar(self):			return Scalar(self.x)
    519 	def toVec2(self):			return Vec2(self.x, self.y)
    520 	def toVec3(self):			return Vec3(self.x, self.y, self.z)
    521 	def toVec4(self):			return Vec4(self.x, self.y, self.z, 0.0)
    522 	def toUVec2(self):			return UVec2(self.x, self.y)
    523 	def toUVec3(self):			return UVec3(self.x, self.y, self.z)
    524 	def toUVec4(self):			return UVec4(self.x, self.y, self.z, 0.0)
    525 	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));
    526 
    527 	def toFloat(self):			return Vec3(float(self.x), float(self.y), float(self.z))
    528 	def toInt(self):			return Vec3(int(self.x), int(self.y), int(self.z))
    529 	def toUint(self):			return UVec3(int(self.x), int(self.y), int(self.z))
    530 	def toBool(self):			return Vec3(bool(self.x), bool(self.y), bool(self.z))
    531 
    532 	def getNumScalars(self):	return 3
    533 	def getScalars(self):		return [self.x, self.y, self.z]
    534 
    535 	def typeString(self):
    536 		if isinstance(self.x, bool):
    537 			return "bvec3"
    538 		elif isinstance(self.x, int):
    539 			return "ivec3"
    540 		elif isinstance(self.x, float):
    541 			return "vec3"
    542 		else:
    543 			assert False
    544 
    545 	def vec4Swizzle(self):
    546 		return ".xyzx"
    547 
    548 	def __str__(self):
    549 		if isinstance(self.x, bool):
    550 			return "bvec3(%s, %s, %s)" % (str(self.x).lower(), str(self.y).lower(), str(self.z).lower())
    551 		elif isinstance(self.x, int):
    552 			return "ivec3(%i, %i, %i)" % (self.x, self.y, self.z)
    553 		elif isinstance(self.x, float):
    554 			return "vec3(%s, %s, %s)" % (self.x, self.y, self.z)
    555 		else:
    556 			assert False
    557 
    558 	def distance(self, v):
    559 		assert isinstance(v, Vec3)
    560 		return (self - v).length()
    561 
    562 	def dot(self, v):
    563 		assert isinstance(v, Vec3)
    564 		return Scalar(self.x*v.x + self.y*v.y + self.z*v.z)
    565 
    566 	def cross(self, v):
    567 		assert isinstance(v, Vec3)
    568 		return Vec3(self.y*v.z - v.y*self.z,
    569 					self.z*v.x - v.z*self.x,
    570 					self.x*v.y - v.x*self.y)
    571 
    572 	def abs(self):
    573 		if isinstance(self.x, bool):
    574 			return Vec3(self.x, self.y, self.z)
    575 		else:
    576 			return Vec3(abs(self.x), abs(self.y), abs(self.z))
    577 
    578 	def __neg__(self):
    579 		return Vec3(-self.x, -self.y, -self.z)
    580 
    581 	def __add__(self, val):
    582 		if isinstance(val, Scalar):
    583 			return Vec3(self.x + val, self.y + val)
    584 		elif isinstance(val, Vec3):
    585 			return Vec3(self.x + val.x, self.y + val.y, self.z + val.z)
    586 		else:
    587 			assert False
    588 
    589 	def __sub__(self, val):
    590 		return self + (-val)
    591 
    592 	def __mul__(self, val):
    593 		if isinstance(val, Scalar):
    594 			val = val.toVec3()
    595 		assert isinstance(val, Vec3)
    596 		return Vec3(self.x * val.x, self.y * val.y, self.z * val.z)
    597 
    598 	def __div__(self, val):
    599 		if isinstance(val, Scalar):
    600 			return Vec3(self.x / val.x, self.y / val.x, self.z / val.x)
    601 		elif isinstance(val, Vec3):
    602 			return Vec3(self.x / val.x, self.y / val.y, self.z / val.z)
    603 		else:
    604 			assert False
    605 
    606 	def boolAny(self):	return Scalar(self.x or self.y or self.z)
    607 	def boolAll(self):	return Scalar(self.x and self.y and self.z)
    608 	def boolNot(self):	return Vec3(not self.x, not self.y, not self.z)
    609 
    610 class UVec3(Vec3):
    611 	def __init__(self, x, y, z):
    612 		assert isinstance(x, int) and isinstance(y, int) and isinstance(z, int)
    613 		assert x >= 0 and y >= 0 and z >= 0
    614 		Vec3.__init__(self, x, y, z)
    615 
    616 	def typeString(self):
    617 		return "uvec3"
    618 
    619 	def __str__(self):
    620 		return "uvec3(%i, %i, %i)" % (self.x, self.y, self.z)
    621 
    622 	def abs(self):
    623 		return Vec3.abs(self).toUint()
    624 
    625 class Vec4(Vec):
    626 	def __init__(self, x, y, z, w):
    627 		assert((x.__class__ == y.__class__) and (x.__class__ == z.__class__) and (x.__class__ == w.__class__))
    628 		self.x = x
    629 		self.y = y
    630 		self.z = z
    631 		self.w = w
    632 
    633 	def applyUnary(self, func):			return Vec4(func(self.x), func(self.y), func(self.z), func(self.w))
    634 	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))
    635 
    636 	def expandVec(self, val):	return val.toVec4()
    637 	def toScalar(self):			return Scalar(self.x)
    638 	def toVec2(self):			return Vec2(self.x, self.y)
    639 	def toVec3(self):			return Vec3(self.x, self.y, self.z)
    640 	def toVec4(self):			return Vec4(self.x, self.y, self.z, self.w)
    641 	def toUVec2(self):			return UVec2(self.x, self.y)
    642 	def toUVec3(self):			return UVec3(self.x, self.y, self.z)
    643 	def toUVec4(self):			return UVec4(self.x, self.y, self.z, self.w)
    644 	def toMat2(self):			return Mat2(float(self.x), float(self.y), float(self.z), float(self.w))
    645 	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));
    646 
    647 	def toFloat(self):			return Vec4(float(self.x), float(self.y), float(self.z), float(self.w))
    648 	def toInt(self):			return Vec4(int(self.x), int(self.y), int(self.z), int(self.w))
    649 	def toUint(self):			return UVec4(int(self.x), int(self.y), int(self.z), int(self.w))
    650 	def toBool(self):			return Vec4(bool(self.x), bool(self.y), bool(self.z), bool(self.w))
    651 
    652 	def getNumScalars(self):	return 4
    653 	def getScalars(self):		return [self.x, self.y, self.z, self.w]
    654 
    655 	def typeString(self):
    656 		if isinstance(self.x, bool):
    657 			return "bvec4"
    658 		elif isinstance(self.x, int):
    659 			return "ivec4"
    660 		elif isinstance(self.x, float):
    661 			return "vec4"
    662 		else:
    663 			assert False
    664 
    665 	def vec4Swizzle(self):
    666 		return ""
    667 
    668 	def __str__(self):
    669 		if isinstance(self.x, bool):
    670 			return "bvec4(%s, %s, %s, %s)" % (str(self.x).lower(), str(self.y).lower(), str(self.z).lower(), str(self.w).lower())
    671 		elif isinstance(self.x, int):
    672 			return "ivec4(%i, %i, %i, %i)" % (self.x, self.y, self.z, self.w)
    673 		elif isinstance(self.x, float):
    674 			return "vec4(%s, %s, %s, %s)" % (self.x, self.y, self.z, self.w)
    675 		else:
    676 			assert False
    677 
    678 	def distance(self, v):
    679 		assert isinstance(v, Vec4)
    680 		return (self - v).length()
    681 
    682 	def dot(self, v):
    683 		assert isinstance(v, Vec4)
    684 		return Scalar(self.x*v.x + self.y*v.y + self.z*v.z + self.w*v.w)
    685 
    686 	def abs(self):
    687 		if isinstance(self.x, bool):
    688 			return Vec4(self.x, self.y, self.z, self.w)
    689 		else:
    690 			return Vec4(abs(self.x), abs(self.y), abs(self.z), abs(self.w))
    691 
    692 	def __neg__(self):
    693 		return Vec4(-self.x, -self.y, -self.z, -self.w)
    694 
    695 	def __add__(self, val):
    696 		if isinstance(val, Scalar):
    697 			return Vec3(self.x + val, self.y + val)
    698 		elif isinstance(val, Vec4):
    699 			return Vec4(self.x + val.x, self.y + val.y, self.z + val.z, self.w + val.w)
    700 		else:
    701 			assert False
    702 
    703 	def __sub__(self, val):
    704 		return self + (-val)
    705 
    706 	def __mul__(self, val):
    707 		if isinstance(val, Scalar):
    708 			val = val.toVec4()
    709 		assert isinstance(val, Vec4)
    710 		return Vec4(self.x * val.x, self.y * val.y, self.z * val.z, self.w * val.w)
    711 
    712 	def __div__(self, val):
    713 		if isinstance(val, Scalar):
    714 			return Vec4(self.x / val.x, self.y / val.x, self.z / val.x, self.w / val.x)
    715 		elif isinstance(val, Vec4):
    716 			return Vec4(self.x / val.x, self.y / val.y, self.z / val.z, self.w / val.w)
    717 		else:
    718 			assert False
    719 
    720 	def boolAny(self):	return Scalar(self.x or self.y or self.z or self.w)
    721 	def boolAll(self):	return Scalar(self.x and self.y and self.z and self.w)
    722 	def boolNot(self):	return Vec4(not self.x, not self.y, not self.z, not self.w)
    723 
    724 class UVec4(Vec4):
    725 	def __init__(self, x, y, z, w):
    726 		assert isinstance(x, int) and isinstance(y, int) and isinstance(z, int) and isinstance(w, int)
    727 		assert x >= 0 and y >= 0 and z >= 0 and w >= 0
    728 		Vec4.__init__(self, x, y, z, w)
    729 
    730 	def typeString(self):
    731 		return "uvec4"
    732 
    733 	def __str__(self):
    734 		return "uvec4(%i, %i, %i, %i)" % (self.x, self.y, self.z, self.w)
    735 
    736 	def abs(self):
    737 		return Vec4.abs(self).toUint()
    738 
    739 # \note Column-major storage.
    740 class Mat(object):
    741 	def __init__ (self, numCols, numRows, scalars):
    742 		assert len(scalars) == numRows*numCols
    743 		self.numCols	= numCols
    744 		self.numRows	= numRows
    745 		self.scalars	= scalars
    746 
    747 	@staticmethod
    748 	def fromScalar (numCols, numRows, scalar):
    749 		scalars = []
    750 		for col in range(0, numCols):
    751 			for row in range(0, numRows):
    752 				scalars.append(scalar if col == row else 0.0)
    753 		return Mat(numCols, numRows, scalars)
    754 
    755 	@staticmethod
    756 	def identity (numCols, numRows):
    757 		return Mat.fromScalar(numCols, numRows, 1.0)
    758 
    759 	def get (self, colNdx, rowNdx):
    760 		assert 0 <= colNdx and colNdx < self.numCols
    761 		assert 0 <= rowNdx and rowNdx < self.numRows
    762 		return self.scalars[colNdx*self.numRows + rowNdx]
    763 
    764 	def set (self, colNdx, rowNdx, scalar):
    765 		assert 0 <= colNdx and colNdx < self.numCols
    766 		assert 0 <= rowNdx and rowNdx < self.numRows
    767 		self.scalars[colNdx*self.numRows + rowNdx] = scalar
    768 
    769 	def toMatrix (self, numCols, numRows):
    770 		res = Mat.identity(numCols, numRows)
    771 		for col in range(0, min(self.numCols, numCols)):
    772 			for row in range(0, min(self.numRows, numRows)):
    773 				res.set(col, row, self.get(col, row))
    774 		return res
    775 
    776 	def toMat2 (self):		return self.toMatrix(2, 2)
    777 	def toMat2x3 (self):	return self.toMatrix(2, 3)
    778 	def toMat2x4 (self):	return self.toMatrix(2, 4)
    779 	def toMat3x2 (self):	return self.toMatrix(3, 2)
    780 	def toMat3 (self):		return self.toMatrix(3, 3)
    781 	def toMat3x4 (self):	return self.toMatrix(3, 4)
    782 	def toMat4x2 (self):	return self.toMatrix(4, 2)
    783 	def toMat4x3 (self):	return self.toMatrix(4, 3)
    784 	def toMat4 (self):		return self.toMatrix(4, 4)
    785 
    786 	def typeString(self):
    787 		if self.numRows == self.numCols:
    788 			return "mat%d" % self.numRows
    789 		else:
    790 			return "mat%dx%d" % (self.numCols, self.numRows)
    791 
    792 	def __str__(self):
    793 		return "%s(%s)" % (self.typeString(), ", ".join(["%s" % s for s in self.scalars]))
    794 
    795 	def isTypeEqual (self, other):
    796 		return isinstance(other, Mat) and self.numRows == other.numRows and self.numCols == other.numCols
    797 
    798 	def isEqual(self, other):
    799 		assert self.isTypeEqual(other)
    800 		return (self.scalars == other.scalars)
    801 
    802 	def compMul(self, val):
    803 		assert self.isTypeEqual(val)
    804 		return Mat(self.numRows, self.numCols, [self.scalars(i) * val.scalars(i) for i in range(self.numRows*self.numCols)])
    805 
    806 class Mat2(Mat):
    807 	def __init__(self, m00, m01, m10, m11):
    808 		Mat.__init__(self, 2, 2, [m00, m10, m01, m11])
    809 
    810 class Mat3(Mat):
    811 	def __init__(self, m00, m01, m02, m10, m11, m12, m20, m21, m22):
    812 		Mat.__init__(self, 3, 3, [m00, m10, m20,
    813 								  m01, m11, m21,
    814 								  m02, m12, m22])
    815 
    816 class Mat4(Mat):
    817 	def __init__(self, m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33):
    818 		Mat.__init__(self, 4, 4, [m00, m10, m20, m30,
    819 								  m01, m11, m21, m31,
    820 								  m02, m12, m22, m32,
    821 								  m03, m13, m23, m33])
    822