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 23import re 24import math 25import random 26 27PREAMBLE = """ 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 32class CaseGroup(object): 33 def __init__(self, name, description, children): 34 self.name = name 35 self.description = description 36 self.children = children 37 38class ShaderCase(object): 39 def __init__(self): 40 pass 41 42g_processedCases = {} 43 44def 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 51def 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 65def 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 78def 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 86def 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 105def shuffled(lst): 106 tmp = lst[:] 107 random.shuffle(tmp) 108 return tmp 109 110def 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 115def toFloat(lst): return [Scalar(float(v.x)) for v in lst] 116def toInt(lst): return [Scalar(int(v.x)) for v in lst] 117def toUint(lst): return [Uint(int(v.x)) for v in lst] 118def toBool(lst): return [Scalar(bool(v.x)) for v in lst] 119def toVec4(lst): return [v.toFloat().toVec4() for v in lst] 120def toVec3(lst): return [v.toFloat().toVec3() for v in lst] 121def toVec2(lst): return [v.toFloat().toVec2() for v in lst] 122def toIVec4(lst): return [v.toInt().toVec4() for v in lst] 123def toIVec3(lst): return [v.toInt().toVec3() for v in lst] 124def toIVec2(lst): return [v.toInt().toVec2() for v in lst] 125def toBVec4(lst): return [v.toBool().toVec4() for v in lst] 126def toBVec3(lst): return [v.toBool().toVec3() for v in lst] 127def toBVec2(lst): return [v.toBool().toVec2() for v in lst] 128def toUVec4(lst): return [v.toUint().toUVec4() for v in lst] 129def toUVec3(lst): return [v.toUint().toUVec3() for v in lst] 130def toUVec2(lst): return [v.toUint().toUVec2() for v in lst] 131def toMat2(lst): return [v.toMat2() for v in lst] 132def toMat2x3(lst): return [v.toMat2x3() for v in lst] 133def toMat2x4(lst): return [v.toMat2x4() for v in lst] 134def toMat3x2(lst): return [v.toMat3x2() for v in lst] 135def toMat3(lst): return [v.toMat3() for v in lst] 136def toMat3x4(lst): return [v.toMat3x4() for v in lst] 137def toMat4x2(lst): return [v.toMat4x2() for v in lst] 138def toMat4x3(lst): return [v.toMat4x3() for v in lst] 139def toMat4(lst): return [v.toMat4() for v in lst] 140 141# Random value generation. 142 143class 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 164def glslSign(a): return 0.0 if (a == 0) else +1.0 if (a > 0.0) else -1.0 165def glslMod(x, y): return x - y*math.floor(x/y) 166def glslClamp(x, mn, mx): return mn if (x < mn) else mx if (x > mx) else x 167 168class 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 228class 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 336class 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 362class 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 395class 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 490class 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 505class 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 608class 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 623class 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 722class 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. 738class 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 804class Mat2(Mat): 805 def __init__(self, m00, m01, m10, m11): 806 Mat.__init__(self, 2, 2, [m00, m10, m01, m11]) 807 808class 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 814class 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