NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

gradients.py (11188B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\client\script\graphics\resourceConstructors\gradients.py
      2 import blue
      3 import trinity
      4 import struct
      5 import math
      6 from functools import reduce
      7 
      8 def isVector(a):
      9     return hasattr(a, '__iter__')
     10 
     11 
     12 def Lerp(a, b, u):
     13 
     14     def LerpValue(x, y):
     15         return x * (1.0 - u) + y * u
     16 
     17     if not isVector(a):
     18         return LerpValue(a, b)
     19     else:
     20         return map(LerpValue, a, b)
     21 
     22 
     23 def Cosine(a, b, u):
     24 
     25     def CosValue(x, y):
     26         cosU = math.cos(u * math.pi * 0.5)
     27         return x * cosU * cosU + y * (1.0 - cosU * cosU)
     28 
     29     if not isVector(a):
     30         return CosValue(a, b)
     31     else:
     32         return map(CosValue, a, b)
     33 
     34 
     35 def v_op(a, b, op):
     36     if isVector(a):
     37         if isVector(b):
     38             return map(op, a, b)
     39         return map(lambda x: op(x, b), a)
     40     elif isVector(b):
     41         return map(lambda x: op(a, x), b)
     42     else:
     43         return op(a, b)
     44 
     45 
     46 def v_add(a, b):
     47     return v_op(a, b, lambda x, y: x + y)
     48 
     49 
     50 def v_sub(a, b):
     51     return v_op(a, b, lambda x, y: x - y)
     52 
     53 
     54 def v_mul(a, b):
     55     return v_op(a, b, lambda x, y: x * y)
     56 
     57 
     58 def v_div(a, b):
     59     return v_op(a, b, lambda x, y: x / y)
     60 
     61 
     62 def v_dot(a, b):
     63     return reduce(lambda x, y: x + y, v_mul(a, b))
     64 
     65 
     66 def v_len(a):
     67     if isVector(a):
     68         return math.sqrt(v_dot(a, a))
     69     return a
     70 
     71 
     72 def v_unit(a):
     73     l = v_len(a)
     74     if -1e-05 < abs(l) < 1e-05:
     75         l = 1.0
     76     return v_div(a, l)
     77 
     78 
     79 def Bezier(a, b, c, d, u):
     80     inVal = v_sub(b, a)
     81     tweenVal = v_sub(c, b)
     82     outVal = v_sub(d, c)
     83     tanIn = v_mul(v_add(inVal, tweenVal), 0.5)
     84     tanOut = v_mul(v_add(tweenVal, outVal), 0.5)
     85     b1 = v_add(b, v_mul(tanIn, 0.33))
     86     c1 = v_sub(c, v_mul(tanOut, 0.33))
     87     v = 1.0 - u
     88     return v_add(v_add(v_mul(b, math.pow(v, 3)), v_mul(b1, u * 3.0 * math.pow(v, 2))), v_add(v_mul(c1, v * 3.0 * math.pow(u, 2)), v_mul(c, math.pow(u, 3))))
     89 
     90 
     91 def SampleGradient(divs, points, x, interpMode = 'linear'):
     92     if x < divs[0]:
     93         return points[0]
     94     elif x >= divs[-1]:
     95         return points[-1]
     96     n = len(points)
     97     minX, maxX = (0, 1)
     98     index = 0
     99     for i, xPrev, xNext in zip(range(n), divs, divs[1:]):
    100         if xPrev <= x < xNext:
    101             minX = xPrev
    102             maxX = xNext
    103             index = i
    104             break
    105         minX = xPrev
    106         index = 1
    107 
    108     u = (x - minX) / (maxX - minX) if maxX != minX else 0.0
    109 
    110     def fetch(i):
    111         return points[min(n - 1, max(0, i))]
    112 
    113     if interpMode == 'bezier':
    114         return Bezier(fetch(index - 1), fetch(index), fetch(index + 1), fetch(index + 2), u)
    115     elif interpMode == 'cosine':
    116         return Cosine(fetch(index), fetch(index + 1), u)
    117     else:
    118         return Lerp(fetch(index), fetch(index + 1), u)
    119 
    120 
    121 def ColourByteClamp(r, g, b, a):
    122     r = int(min(255, max(0, r * 255)))
    123     g = int(min(255, max(0, g * 255)))
    124     b = int(min(255, max(0, b * 255)))
    125     a = int(min(255, max(0, a * 255)))
    126     return (r,
    127      g,
    128      b,
    129      a)
    130 
    131 
    132 def Gradient(paramString):
    133     params = {'rgbInterp': 'linear',
    134      'rgbDivs': [0.0,
    135                  0.33,
    136                  0.66,
    137                  1.0],
    138      'rgbPoints': [(0, 0, 1),
    139                    (0, 1, 0),
    140                    (1, 0, 0),
    141                    (0, 0.5, 0.5)],
    142      'alphaInterp': 'linear',
    143      'alphaDivs': [0, 1],
    144      'alphaPoints': [1.0, 1.0],
    145      'textureSize': 256}
    146     if paramString.endswith('}atlas'):
    147         paramString = paramString[:-5]
    148     try:
    149         if paramString:
    150             params.update(eval(paramString))
    151     except:
    152         pass
    153 
    154     textureSize = params['textureSize']
    155     texture = trinity.textureAtlasMan.atlases[0].CreateTexture(textureSize, 1)
    156     locked = texture.LockBufferAndMargin(None, False)
    157     if locked:
    158         buf = locked[0]
    159         width = locked[1]
    160         height = locked[2]
    161         pitch = locked[3]
    162         margin = locked[4]
    163         try:
    164             for y in range(height):
    165                 for xi in range(width):
    166                     x = (xi - margin) / float(textureSize - 1)
    167                     x = max(0.0, min(1.0, x))
    168                     r, g, b = SampleGradient(params['rgbDivs'], params['rgbPoints'], x, params['rgbInterp'])
    169                     a = SampleGradient(params['alphaDivs'], params['alphaPoints'], x, params['alphaInterp'])
    170                     r, g, b, a = ColourByteClamp(r, g, b, a)
    171                     buf[y * pitch + xi * 4 + 0] = struct.pack('B', b)
    172                     buf[y * pitch + xi * 4 + 1] = struct.pack('B', g)
    173                     buf[y * pitch + xi * 4 + 2] = struct.pack('B', r)
    174                     buf[y * pitch + xi * 4 + 3] = struct.pack('B', a)
    175 
    176         finally:
    177             texture.UnlockBuffer()
    178 
    179     return texture
    180 
    181 
    182 def GradientRadial(paramString):
    183     params = {'toCorners': True,
    184      'rgbInterp': 'linear',
    185      'rgbDivs': [0.0,
    186                  0.33,
    187                  0.66,
    188                  1.0],
    189      'rgbPoints': [(0, 0, 1),
    190                    (0, 1, 0),
    191                    (1, 0, 0),
    192                    (0, 0.5, 0.5)],
    193      'alphaInterp': 'linear',
    194      'alphaDivs': [0, 1],
    195      'alphaPoints': [1.0, 1.0],
    196      'textureSize': (256, 256)}
    197     if paramString.endswith('}atlas'):
    198         paramString = paramString[:-5]
    199     try:
    200         if paramString:
    201             params.update(eval(paramString))
    202     except:
    203         pass
    204 
    205     textureSize = params['textureSize']
    206     if not hasattr(textureSize, '__iter__'):
    207         textureSize = (textureSize, textureSize)
    208     texture = trinity.textureAtlasMan.atlases[0].CreateTexture(textureSize[0], textureSize[1])
    209     locked = texture.LockBufferAndMargin(None, False)
    210     if locked:
    211         buf = locked[0]
    212         width = locked[1]
    213         height = locked[2]
    214         pitch = locked[3]
    215         margin = locked[4]
    216         try:
    217             for yi in range(height):
    218                 y = 2.0 * ((yi - margin) / float(height - 1) - 0.5)
    219                 y = max(-1.0, min(y, 1.0))
    220                 for xi in range(width):
    221                     x = 2.0 * ((xi - margin) / float(width - 1) - 0.5)
    222                     x = max(-1.0, min(x, 1.0))
    223                     rad = math.sqrt(x * x + y * y)
    224                     if params['toCorners']:
    225                         rad /= 1.41421
    226                     r, g, b = SampleGradient(params['rgbDivs'], params['rgbPoints'], rad, params['rgbInterp'])
    227                     a = SampleGradient(params['alphaDivs'], params['alphaPoints'], rad, params['alphaInterp'])
    228                     r, g, b, a = ColourByteClamp(r, g, b, a)
    229                     buf[yi * pitch + xi * 4 + 0] = struct.pack('B', b)
    230                     buf[yi * pitch + xi * 4 + 1] = struct.pack('B', g)
    231                     buf[yi * pitch + xi * 4 + 2] = struct.pack('B', r)
    232                     buf[yi * pitch + xi * 4 + 3] = struct.pack('B', a)
    233 
    234         finally:
    235             texture.UnlockBuffer()
    236 
    237     return texture
    238 
    239 
    240 def SampleGradient2D(subdivsX, subdivsY, pointsX, pointsY, x, y, interpMode = 'linear'):
    241     indexX, indexY = (0, 0)
    242     minX, minY, maxX, maxY = (0, 0, 1, 1)
    243     found = False
    244     for idx, xCurr, xNext in zip(range(len(subdivsX)), subdivsX, subdivsX[1:]):
    245         if xCurr <= x < xNext:
    246             indexX = idx
    247             minX = xCurr
    248             maxX = xNext
    249             found = True
    250             break
    251 
    252     if found:
    253         u = (x - minX) / (maxX - minX)
    254     else:
    255         indexX = len(pointsX) - 1
    256         u = 1
    257     found = False
    258     for idx, yCurr, yNext in zip(range(len(subdivsY)), subdivsY, subdivsY[1:]):
    259         if yCurr <= y < yNext:
    260             indexY = idx
    261             minY = yCurr
    262             maxY = yNext
    263             found = True
    264             break
    265 
    266     if found:
    267         v = (y - minY) / (maxY - minY)
    268     else:
    269         indexY = len(pointsY) - 1
    270         v = 1
    271 
    272     def fetch(i, points):
    273         i = min(len(points) - 1, max(0, i))
    274         return points[i]
    275 
    276     if interpMode == 'bezier':
    277         colorX = Bezier(fetch(indexX - 1, pointsX), fetch(indexX, pointsX), fetch(indexX + 1, pointsX), fetch(indexX + 2, pointsX), u)
    278         colorY = Bezier(fetch(indexY - 1, pointsY), fetch(indexY, pointsY), fetch(indexY + 1, pointsY), fetch(indexY + 2, pointsY), v)
    279     elif interpMode == 'cosine':
    280         colorX = Cosine(fetch(indexX, pointsX), fetch(indexX + 1, pointsX), u)
    281         colorY = Cosine(fetch(indexY, pointsY), fetch(indexY + 1, pointsY), v)
    282     else:
    283         colorX = Lerp(fetch(indexX, pointsX), fetch(indexX + 1, pointsX), u)
    284         colorY = Lerp(fetch(indexY, pointsY), fetch(indexY + 1, pointsY), v)
    285     if isVector(colorX):
    286         color = (colorX[0] * colorY[0], colorX[1] * colorY[1], colorX[2] * colorY[2])
    287     else:
    288         color = colorX * colorY
    289     return color
    290 
    291 
    292 def Gradient2D(paramString):
    293     params = {'rgbHorizontal': [0, 1],
    294      'rgbVertical': [0, 1],
    295      'rgbDataHorizontal': [(1, 1, 1), (0, 0, 0)],
    296      'rgbDataVertical': [(1, 1, 1), (0, 0, 0)],
    297      'alphaHorizontal': [0, 1],
    298      'alphaVertical': [0, 1],
    299      'alphaDataHorizontal': [1, 0],
    300      'alphaDataVertical': [1, 0],
    301      'textureSize': (256, 256),
    302      'rgbInterp': 'linear',
    303      'alphaInterp': 'linear'}
    304     if paramString.endswith('}atlas'):
    305         paramString = paramString[:-5]
    306     try:
    307         if paramString:
    308             params.update(eval(paramString))
    309     except:
    310         pass
    311 
    312     textureSize = params['textureSize']
    313     if not hasattr(textureSize, '__iter__'):
    314         textureSize = (textureSize, textureSize)
    315     texture = trinity.textureAtlasMan.atlases[0].CreateTexture(textureSize[0], textureSize[1])
    316     locked = texture.LockBufferAndMargin(None, False)
    317     if locked:
    318         buf = locked[0]
    319         width = locked[1]
    320         height = locked[2]
    321         pitch = locked[3]
    322         margin = locked[4]
    323         try:
    324             rgbHorizontal = params['rgbHorizontal']
    325             rgbVertical = params['rgbVertical']
    326             rgbDataHorizontal = params['rgbDataHorizontal']
    327             rgbDataVertical = params['rgbDataVertical']
    328             rgbInterp = params['rgbInterp']
    329             alphaHorizontal = params['alphaHorizontal']
    330             alphaVertical = params['alphaVertical']
    331             alphaDataHorizontal = params['alphaDataHorizontal']
    332             alphaDataVertical = params['alphaDataVertical']
    333             alphaInterp = params['alphaInterp']
    334             for yi in xrange(height):
    335                 y = (yi - margin) / float(textureSize[1] - 1)
    336                 y = max(0.0, min(y, 1.0))
    337                 for xi in xrange(width):
    338                     x = (xi - margin) / float(textureSize[0] - 1)
    339                     x = max(0.0, min(x, 1.0))
    340                     r, g, b = SampleGradient2D(rgbHorizontal, rgbVertical, rgbDataHorizontal, rgbDataVertical, x, y, rgbInterp)
    341                     a = SampleGradient2D(alphaHorizontal, alphaVertical, alphaDataHorizontal, alphaDataVertical, x, y, alphaInterp)
    342                     r, g, b, a = ColourByteClamp(r, g, b, a)
    343                     buf[yi * pitch + xi * 4 + 0] = struct.pack('B', b)
    344                     buf[yi * pitch + xi * 4 + 1] = struct.pack('B', g)
    345                     buf[yi * pitch + xi * 4 + 2] = struct.pack('B', r)
    346                     buf[yi * pitch + xi * 4 + 3] = struct.pack('B', a)
    347 
    348         finally:
    349             texture.UnlockBuffer()
    350 
    351     return texture