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