예제 #1
0
 def readCameraData(self):
     if self.__cameraData is None:
         userFile = FilePath(currentProjectFilePath() + '.user')
         xCamera = None
         if userFile.exists():
             xRoot = parseXMLWithIncludes(userFile)
             for xSub in xRoot:
                 if xSub.attrib['name'] == self.__filePath.name():
                     xCamera = xSub
                     break
         if xCamera is None:  # legacy support
             xCamera = parseXMLWithIncludes(self.__filePath)
         self.__cameraData = CameraTransform(
             *[float(x) for x in xCamera.attrib['camera'].split(',')])
     return self.__cameraData
예제 #2
0
def readChannelTemplates():
    templatesDir = currentTemplatesDirectory()
    channelTemplates = templatesDir.join('uniforms.xml')
    result = OrderedDict()

    # legacy fallback
    if not channelTemplates.exists():
        curves = OrderedDict()
        curves['uOrigin.x'] = Curve()
        curves['uOrigin.y'] = Curve()
        curves['uOrigin.z'] = Curve()
        curves['uAngles.x'] = Curve()
        curves['uAngles.y'] = Curve()
        curves['uAngles.z'] = Curve()
        result['default'] = curves
        return result

    xRoot = parseXMLWithIncludes(channelTemplates)
    for xTemplate in xRoot:
        name = xTemplate.attrib['name']
        curves = OrderedDict()
        result[name] = curves
        for xChannel in xTemplate:
            curve = Curve()
            curves[xChannel.attrib['name']] = curve
            Key(0.0, float(xChannel.attrib['value']), curve).reInsert()

    return result
예제 #3
0
def Template(templatePath):
    assert isinstance(templatePath, FilePath)
    global _templates
    key = os.path.abspath(templatePath).lower()
    try:
        return _templates[key]
    except:
        xTemplate = parseXMLWithIncludes(templatePath)
        if _templates:
            raise RuntimeError('Found multiple templates in project, this is currently not supported by the player code.')
        _templates[key] = xTemplate
        return xTemplate
예제 #4
0
def _deserializeSceneShots(sceneName):
    sceneFile = currentScenesDirectory().join(sceneName.ensureExt(SCENE_EXT))
    xScene = parseXMLWithIncludes(sceneFile)

    for xShot in xScene:
        name = xShot.attrib['name']
        start = float(xShot.attrib['start'])
        end = float(xShot.attrib['end'])
        speed = float(xShot.attrib.get(
            'speed', 1.0))  # using get for legacy file support
        preroll = float(xShot.attrib.get('preroll', 0.0))

        curves = OrderedDict()
        textures = OrderedDict()
        for xEntry in xShot:
            if xEntry.tag.lower() == 'channel':
                curveName = xEntry.attrib['name']
                keys = []
                if xEntry.text:
                    keys = xEntry.text.split(',')
                curve = Curve()
                for i in range(0, len(keys), 8):
                    curve.addKeyWithTangents(
                        tangentBroken=int(keys[i + 6]),
                        tangentMode=int(keys[i + 7]),
                        *[float(x) for x in keys[i:i + 6]])
                curves[curveName] = curve

            if xEntry.tag.lower() == 'texture':
                textures[xEntry.attrib['name']] = FilePath(
                    xEntry.attrib['path'])

        shot = Shot(name, sceneName, start, end, curves, textures, speed,
                    preroll)
        if 'enabled' in xShot.attrib:
            shot.enabled = xShot.attrib['enabled'] == str(True)
        yield shot
예제 #5
0
def run():
    shots = []
    scenes = []
    scenesDir = currentScenesDirectory()

    for scenePath in scenesDir.iter(join=True):
        if not scenePath.hasExt(SCENE_EXT):
            continue
        sceneDir = FilePath(scenePath.strip()).stripExt()
        xScene = parseXMLWithIncludes(scenePath)

        templatePath = scenesDir.join(scenesDir, xScene.attrib['template'])
        templateDir = templatePath.stripExt()
        xTemplate = Template(templatePath)

        scene = []

        for xPass in xTemplate:
            stitchIds = []
            uniforms = {}
            for xSection in xPass:
                baseDir = sceneDir
                if xSection.tag in ('global', 'shared'):
                    baseDir = templateDir
                shaderFile = baseDir.join(xSection.attrib['path']).abs()
                stitchIds.append(text.addFile(shaderFile))
                for xUniform in xSection:
                    name = xUniform.attrib['name']
                    values = [
                        float(x.strip())
                        for x in xUniform.attrib['value'].split(',')
                    ]
                    uniforms[text.addString(name)] = len(
                        values), floats.addFloats(values, name)

            programId = shaders.fromStitches(stitchIds)

            buffer = int(xPass.attrib.get('buffer', -1))
            outputs = int(xPass.attrib.get('outputs', 1))
            size = int(xPass.attrib.get('size', 0))
            width = int(xPass.attrib.get('width', size))
            height = int(xPass.attrib.get('height', size))
            factor = int(xPass.attrib.get('factor', 1))
            static = int(xPass.attrib.get('static', 0))
            is3d = int(xPass.attrib.get('is3d', 0))
            if buffer != -1:
                buffer = framebuffers.add(buffer, outputs, width, height,
                                          factor, static, is3d)

            i = 0
            key = 'input%s' % i
            inputs = []
            while key in xPass.attrib:
                v = xPass.attrib[key]
                if '.' in v:
                    a, b = v.split('.')
                else:
                    a, b = v, 0
                inputs.append((int(a), int(b)))
                i += 1
                key = 'input%s' % i

            scene.append(passes.add(programId, buffer, inputs, uniforms))

        sceneIndex = len(scenes)
        scenes.append(len(scene))
        scenes += scene

        for xShot in xScene:
            if xShot.attrib.get('enabled', 'True') == 'False':
                continue
            animations = {}
            for xChannel in xShot:
                uname = xChannel.attrib['name']
                n = uname
                x = 0
                if '.' in uname:
                    n, x = uname.rsplit('.', 1)
                    x = 'xyzw'.index(x)
                n = text.addString(n)
                if n not in animations:
                    animations[n] = []
                if not xChannel.text:
                    keyframes = []
                else:
                    keyframes = []
                    for i, v in enumerate(
                            float(v.strip())
                            for v in xChannel.text.split(',')):
                        j = i % 8
                        if j == 0 or j == 4 or j > 5:
                            continue
                        if j == 5:  # out tangent y
                            if v == float(
                                    'inf'
                            ):  # stepped tangents are implemented as out tangentY = positive infinity
                                v = 'FLT_MAX'
                        keyframes.append(v)
                    assert len(keyframes) / 4.0 == int(len(keyframes) /
                                                       4), len(keyframes)
                while len(animations[n]) <= x:
                    animations[n].append(None)
                assert animations[n][x] is None
                animations[n][x] = floats.addFloats(keyframes), len(keyframes)

            for channelStack in animations.values():
                # TODO we can not / do not check if the channelStack length matches the uniform dimensions inside the shader (e.g. are we sure we're not gonna call glUniform2f for a vec3?)
                assert None not in channelStack, 'Animation provided for multiple channels but there is one missing (Y if a vec3 or also Z if a vec4).'

            shots.append((float(xShot.attrib['start']),
                          float(xShot.attrib['end']), sceneIndex, animations))

    # sort shots by start time
    def _serializeShots(shots):
        shots.sort(key=lambda x: x[0])
        shotTimesStart = floats.addFloats(
            [x for shot in shots for x in (shot[0], shot[1])])
        yield '\n\n__forceinline int shotAtBeats(float beats, float& localBeats)\n{\n'
        if len(shots) == 1:
            yield '\tlocalBeats = beats - gFloatData[%s];\n' % shotTimesStart
            yield '\treturn 0;\n'
        else:
            yield '\tint shotTimeCursor = 0;\n'
            yield '\tdo\n\t{\n'
            yield '\t\tif(beats < gFloatData[shotTimeCursor * 2 + %s])\n\t\t{\n' % (
                shotTimesStart + 1)
            yield '\t\t\tlocalBeats = beats - gFloatData[shotTimeCursor * 2 + %s];\n' % shotTimesStart
            yield '\t\t\treturn shotTimeCursor;\n'
            yield '\t\t}\n'
            yield '\t}\n\twhile(++shotTimeCursor < %s);\n' % len(shots)
            yield '\treturn -1;\n'
        yield '}\n'

        global gShotScene
        gShotScene = ints.addInts([shot[2] for shot in shots])
        flatAnimationData = []
        animationDataPtrs = []
        for shot in shots:
            animationDataPtrs += [len(flatAnimationData), len(shot[3].keys())]
            global gAnimEntriesMax
            gAnimEntriesMax = max(gAnimEntriesMax, len(shot[3].keys()))
            for uniformStringId in shot[3]:
                animationData = shot[3][uniformStringId]
                flatAnimationData += [uniformStringId, len(animationData)]
                for pair in animationData:
                    flatAnimationData += pair
                flatAnimationData += [0] * (2 * (4 - len(animationData)))

        global gShotAnimationDataIds
        gShotAnimationDataIds = ints.addInts(animationDataPtrs)
        global gShotUniformData
        gShotUniformData = ints.addInts(flatAnimationData)

    def _serializeAll(scenes, shots):
        buffer = list(_serializeShots(shots))
        for serializable in (text, floats):
            for ln in serializable.serialize():
                yield ln
        buffer2 = []
        for serializable in (shaders, framebuffers, passes):
            buffer2 += list(serializable.serialize())
        global gScenePassIds
        gScenePassIds = ints.addInts(scenes)
        for ln in ints.serialize():
            yield ln
        for ln in buffer2:
            yield ln
        for ln in buffer:
            yield ln

    data = [''.join(_serializeAll(scenes, shots))]
    data.append(
        """\n\n__forceinline float evalCurve(const float* data, int numFloats, float beats)
{
\tif(numFloats == 4 || beats <= data[1]) // 1 key or evaluating before first frame
\t\treturn data[2];

\t// Find index of first key that has a bigger time than our current time
\t// if none, this will be the index of the last key.
\tint keyValueCount = numFloats;
\tint rightKeyIndex = 4;
\twhile (rightKeyIndex < keyValueCount - 4 && data[rightKeyIndex + 1] < beats)
\t\trightKeyIndex += 4;

\t// Clamp our sampling time to our range
\tfloat sampleTime = (beats > data[rightKeyIndex + 1]) ? data[rightKeyIndex + 1] : beats;

\t// Retrieve our spline points
\tfloat y0 = data[rightKeyIndex - 2];
\tfloat y1 = data[rightKeyIndex - 1]; 
\t// handle stepped tangents
\tif(y1 == FLT_MAX) return y0;
\tfloat y2 = data[rightKeyIndex];
\tfloat y3 = data[rightKeyIndex + 2];

\tfloat dy = y3 - y0;
\tfloat c0 = y1 + y2 - dy - dy;
\tfloat c1 = dy + dy + dy - y1 - y1 - y2;
\tfloat c2 = y1;
\tfloat c3 = y0;

\t// Determine factor
\tfloat dt = data[rightKeyIndex + 1] - data[rightKeyIndex - 3];
\tfloat t = (sampleTime - data[rightKeyIndex - 3]) / dt;

\treturn t * (t * (t * c0 + c1) + c2) + c3;
}

#define gAnimEntriesMax %s
#define gShotAnimationDataIds %s
#define gShotScene %s
#define gScenePassIds %s
#define gPassProgramsAndTargets %s
#define gShotUniformData %s
#define gFrameBufferData %s
#define gFrameBufferBlockSize %s
#define gProgramCount %s
""" % (gAnimEntriesMax, gShotAnimationDataIds, gShotScene, gScenePassIds,
       gPassProgramsAndTargets, gShotUniformData, gFrameBufferData,
       FrameBufferPool.BLOCK_SIZE, len(shaders.offsets)))

    dst = FilePath(__file__).abs().parent().parent().join(
        'Player', 'generated.hpp')
    with dst.edit() as fh:
        fh.write(''.join(data))
예제 #6
0
def _saveSceneShots(sceneName, shots):
    sceneFile = currentScenesDirectory().join(sceneName.ensureExt(SCENE_EXT))
    xScene = parseXMLWithIncludes(sceneFile)

    # save user camera position per scene
    userFile = currentProjectFilePath().ensureExt('user')
    if userFile.exists():
        xUser = parseXMLWithIncludes(userFile)
    else:
        xUser = cElementTree.Element('user')
    if sceneFile in Scene.cache:
        cameraData = Scene.cache[sceneFile].cameraData()
        if cameraData:
            for xSub in xUser:
                if xSub.tag == 'scene' and xSub.attrib['name'] == sceneName:
                    xSub.attrib['camera'] = ','.join(
                        [str(x) for x in cameraData])
                    break
            else:
                cElementTree.SubElement(
                    xUser, 'scene', {
                        'name': sceneName,
                        'camera': ','.join([str(x) for x in cameraData])
                    })

    with userFile.edit() as fh:
        fh.write(toPrettyXml(xUser))

    # remove old shots
    r = []
    for xShot in xScene:
        r.append(xShot)
    for s in r:
        xScene.remove(s)

    targets = []
    for shot in shots:
        if shot.sceneName == sceneName:
            targets.append(shot)

    for shot in targets:
        xShot = cElementTree.SubElement(
            xScene, 'Shot', {
                'name': shot.name,
                'scene': sceneName,
                'start': str(shot.start),
                'end': str(shot.end),
                'enabled': str(shot.enabled),
                'speed': str(shot.speed),
                'preroll': str(shot.preroll)
            })
        for curveName in shot.curves:
            xChannel = cElementTree.SubElement(xShot, 'Channel', {
                'name': curveName,
                'mode': 'hermite'
            })
            data = []
            for key in shot.curves[curveName]:
                data.append(str(key.inTangent.x))
                data.append(str(key.inTangent.y))
                data.append(str(key.point().x))
                data.append(str(key.point().y))
                data.append(str(key.outTangent.x))
                data.append(str(key.outTangent.y))
                data.append(str(int(key.tangentBroken)))
                data.append(str(key.tangentMode))
            xChannel.text = ','.join(data)
        for texName in shot.textures:
            cElementTree.SubElement(xShot, 'Texture', {
                'name': texName,
                'path': shot.textures[texName]
            })

    with sceneFile.edit() as fh:
        fh.write(toPrettyXml(xScene))
예제 #7
0
def _deserializePasses(sceneFile):
    """
    :type sceneFile: FilePath
    :rtype: list[PassData]
    """
    assert isinstance(sceneFile, FilePath)
    sceneDir = sceneFile.stripExt()
    templatePath = templatePathFromScenePath(sceneFile)
    templateDir = templatePath.stripExt()
    xTemplate = parseXMLWithIncludes(templatePath)
    passes = []
    frameBufferMap = {}
    for xPass in xTemplate:
        buffer = -1
        if 'buffer' in xPass.attrib:
            buffer = xPass.attrib['buffer']
            if buffer not in frameBufferMap:
                frameBufferMap[buffer] = len(frameBufferMap)

        size = None
        if 'size' in xPass.attrib:
            size = int(xPass.attrib['size']), int(xPass.attrib['size'])
        elif 'width' in xPass.attrib and 'height' in xPass.attrib:
            size = int(xPass.attrib['width']), int(xPass.attrib['height'])

        tile = size is not None
        if 'tile' in xPass.attrib:
            tile = xPass.attrib['tile'].lower() == 'true'

        factor = None
        if 'factor' in xPass.attrib:
            factor = int(xPass.attrib['factor'])

        realtime = int(xPass.attrib.get('static', 0)) == 0

        is3d = int(xPass.attrib.get('is3d', 0)) != 0
        if is3d:
            assert (size[0]**0.5) == size[1]
            size = size[0], size[1]

        outputs = int(xPass.attrib.get('outputs', 1))

        inputs = []
        i = 0
        key = 'input%s' % i
        while key in xPass.attrib:
            # input is filename?
            parentPath = currentProjectDirectory()
            fullName = parentPath.join(xPass.attrib[key])
            if fullName.exists():
                inputs.append(FilePath(xPass.attrib[key]))
            else:
                # input is buffer
                if '.' in xPass.attrib[key]:
                    frameBuffer, subTexture = xPass.attrib[key].split('.')
                    frameBuffer, subTexture = frameBuffer, int(subTexture)
                else:
                    frameBuffer, subTexture = xPass.attrib[key], 0

                if frameBuffer not in frameBufferMap:
                    frameBufferMap[frameBuffer] = len(frameBufferMap)
                inputs.append((frameBufferMap[frameBuffer], subTexture))

            i += 1
            key = 'input%s' % i
        vertStitches = []
        fragStitches = []
        uniforms = {}
        for xElement in xPass:
            path = FilePath(xElement.attrib['path'])
            stitches = vertStitches if path.hasExt('vert') else fragStitches
            if xElement.tag.lower() == 'section':
                stitches.append(sceneDir.join(path))
            elif xElement.tag.lower() in ('shared', 'global'):
                stitches.append(templateDir.join(path))
            else:
                raise ValueError('Unknown XML tag in pass: "******"' %
                                 xElement.tag)
            for xUniform in xElement:
                uniforms[xUniform.attrib['name']] = [
                    float(x.strip())
                    for x in xUniform.attrib['value'].split(',')
                ]

        passes.append(
            PassData(vertStitches, fragStitches, uniforms, inputs,
                     frameBufferMap.get(buffer, -1), realtime, size,
                     tile, factor, outputs,
                     xPass.attrib.get('drawcommand', None), is3d,
                     xPass.attrib.get('name', None)))
    return passes
예제 #8
0
def _deserializePasses(sceneFile, models):
    """
    :type sceneFile: FilePath
    :rtype: list[PassData]
    """
    assert isinstance(sceneFile, FilePath)
    sceneDir = sceneFile.stripExt()
    templatePath = templatePathFromScenePath(sceneFile)
    templateDir = templatePath.stripExt()
    modelsDir = currentModelsDirectory()
    xTemplate = parseXMLWithIncludes(templatePath)
    passes = []
    frameBufferMap = {}

    # # Start with adding the models here as passes. Stored by their model name
    # for model in models.models:
    #     inputs = []
    #     if model.name not in frameBufferMap:
    #         frameBufferMap[model.name] = len(frameBufferMap)
    #     size = 256,256
    #     fragStitches = []
    #     fragStitches.append(templateDir.join("header.glsl"))
    #     fragStitches.append(templateDir.join("noiselib.glsl"))
    #     fragStitches.append(templateDir.join("sdf.glsl"))
    #     #fragStitches.append(templateDir.join("test3d.glsl"))
    #     fragStitches.append(modelsDir.join("%s.glsl" % model.name))
    #
    #     # Add a pass for rendering a 3D texture
    #     passes.append(
    #         PassData([], fragStitches, {}, inputs, frameBufferMap.get(model.name, -1), False, size, False, False, 1, None, True, None))

    for xPass in xTemplate:
        buffer = -1
        if 'buffer' in xPass.attrib:
            buffer = xPass.attrib['buffer']
            if buffer not in frameBufferMap:
                frameBufferMap[buffer] = len(frameBufferMap)

        size = None
        if 'size' in xPass.attrib:
            size = int(xPass.attrib['size']), int(xPass.attrib['size'])
        elif 'width' in xPass.attrib and 'height' in xPass.attrib:
            size = int(xPass.attrib['width']), int(xPass.attrib['height'])

        tile = size is not None
        if 'tile' in xPass.attrib:
            tile = xPass.attrib['tile'].lower() == 'true'

        factor = None
        if 'factor' in xPass.attrib:
            factor = int(xPass.attrib['factor'])

        realtime = int(xPass.attrib.get('static', 0)) == 0

        is3d = int(xPass.attrib.get('is3d', 0)) != 0
        if is3d:
            assert (size[0] == size[1])
            size = size[0], size[0]

        outputs = int(xPass.attrib.get('outputs', 1))

        inputs = []
        inputsUniformOverrideNames = {}
        i = 0
        key = 'input%s' % i
        while key in xPass.attrib:
            # input is filename?
            parentPath = currentProjectDirectory()
            fullName = parentPath.join(xPass.attrib[key])
            if fullName.exists():
                inputs.append(FilePath(xPass.attrib[key]))
            else:
                # input is buffer
                if '.' in xPass.attrib[key]:
                    frameBuffer, subTexture = xPass.attrib[key].split('.')
                    frameBuffer, subTexture = frameBuffer, int(subTexture)
                else:
                    frameBuffer, subTexture = xPass.attrib[key], 0

                if frameBuffer not in frameBufferMap:
                    frameBufferMap[frameBuffer] = len(frameBufferMap)
                inputs.append((frameBufferMap[frameBuffer], subTexture))

            i += 1
            key = 'input%s' % i

        inputModels = False
        if 'inputModels' in xPass.attrib:
            inputModels = xPass.attrib['inputModels'].lower() == 'true'

        # Add all model's output buffers as inputs to this pass
        if inputModels:
            for model in models.models:
                bufferIndex = (frameBufferMap[model.name], 0)
                inputs.append(bufferIndex)
                inputsUniformOverrideNames[
                    bufferIndex] = "uModel%s" % model.name

        vertStitches = []
        fragStitches = []
        uniforms = {}
        for xElement in xPass:
            if xElement.tag.lower() == 'section':
                path = FilePath(xElement.attrib['path'])
                stitches = vertStitches if path.hasExt(
                    'vert') else fragStitches
                stitches.append(sceneDir.join(path))
            elif xElement.tag.lower() in ('shared', 'global'):
                path = FilePath(xElement.attrib['path'])
                stitches = vertStitches if path.hasExt(
                    'vert') else fragStitches
                stitches.append(templateDir.join(path))
            elif xElement.tag.lower() == 'models':
                for model in models.models:
                    fragStitches.append(modelsDir.join("%s.glsl" % model.name))
            else:
                raise ValueError('Unknown XML tag in pass: "******"' %
                                 xElement.tag)
            for xUniform in xElement:
                uniforms[xUniform.attrib['name']] = [
                    float(x.strip())
                    for x in xUniform.attrib['value'].split(',')
                ]

        passes.append(
            PassData(vertStitches, fragStitches, uniforms, inputs,
                     frameBufferMap.get(buffer, -1), realtime, size,
                     tile, factor, outputs,
                     xPass.attrib.get('drawcommand', None), is3d,
                     xPass.attrib.get('name',
                                      None), inputsUniformOverrideNames))
    return passes