Example #1
0
    def __init__(self, application):
        self.application = application
        self.width, self.height = width, height = application.mesh_width, application.mesh_height
       
        col = Column() 
        self.input_height = LabelInput('Height', self).append_to(col).input
        self.material = LabelInput('Material', self).append_to(col).input
        
        self.widget = Widget('Terrain', col, id='terrain').append_to(application.workspace)

        self.default_material = Texture(2, 2, GL_RGBA, data=(140, 140, 140, 255)*4)
        self.vertex_texture = Texture(width, height, GL_RGBA32F)
        self.normal_texture = Texture(application.width, application.height, GL_RGBA32F, unit=GL_TEXTURE0)

        self.vertex_fbo = Framebuffer(self.vertex_texture)
        self.normal_fbo = Framebuffer(self.normal_texture)

        self.update_vertex_shader = application.shader('update_vertex.frag')
        self.update_normals_shader = application.shader('update_normals.frag')
        self.update_normals_shader.vars.offsets = 1.0/application.width, 1.0/application.height

        self.reset_vertex = application.shader('reset_vertex.frag')
        self.reset_normals = application.shader('reset_normals.frag')
        self.vbo = self.generate_vbo(width, height)

        self.reset()
        self.updated = None
Example #2
0
    def __init__(self, application):
        self.application = application
        self.width, self.height = width, height = application.mesh_width, application.mesh_height
       
        col = Column() 
        self.input_height = LabelInput('Height', self).append_to(col).input
        self.material = LabelInput('Material', self).append_to(col).input
        
        self.widget = Widget('Terrain', col, id='terrain').append_to(application.workspace)

        self.default_material = Texture(2, 2, GL_RGBA, data=(140, 140, 140, 255)*4)
        self.vertex_texture = Texture(width, height, GL_RGBA32F)
        self.normal_texture = Texture(application.width, application.height, GL_RGBA32F, unit=GL_TEXTURE0)

        self.vertex_fbo = Framebuffer(self.vertex_texture)
        self.normal_fbo = Framebuffer(self.normal_texture)

        self.update_vertex_shader = application.shader('update_vertex.frag')
        self.update_normals_shader = application.shader('update_normals.frag')
        self.update_normals_shader.vars.offsets = 1.0/application.width, 1.0/application.height

        self.reset_vertex = application.shader('reset_vertex.frag')
        self.reset_normals = application.shader('reset_normals.frag')
        self.vbo = self.generate_vbo(width, height)

        self.reset()
        self.updated = None
Example #3
0
    def __init__(self, label, application):
        self.application = application
        self.id = os.urandom(16).encode('hex')

        application.add_node(self)
        self.column = Column()
        bar_area = Area().add_class('widget_bar')
        Label(label).append_to(bar_area)
        Button().append_to(bar_area).on_click = self.delete
        self.texture = application.create_texture()
        self.widget = Widget(bar_area,
                             self.column).add_class('node').append_to(
                                 application.workspace)
        self._parameters = {}
        self.sources = {}
        self.updated = None
        self.optional = []
Example #4
0
    def __init__(self, label, application):
        self.application = application
        self.id = os.urandom(16).encode('hex')

        application.add_node(self)
        self.column = Column()
        bar_area = Area().add_class('widget_bar')
        Label(label).append_to(bar_area)
        Button().append_to(bar_area).on_click = self.delete
        self.texture = application.create_texture()
        self.widget = Widget(bar_area, self.column).add_class('node').append_to(application.workspace)
        self._parameters = {}
        self.sources = {}
        self.updated = None
        self.optional = []
Example #5
0
 def message(self, title, text):
     col = Column()
     Label(text).append_to(col)
     Button('Close').append_to(col).on_click = self.exit
     Widget(title, col,
            dragable=False).append_to(self.root).add_class('message')
Example #6
0
class Terrain(object):
    id = 'terrain'

    def __init__(self, application):
        self.application = application
        self.width, self.height = width, height = application.mesh_width, application.mesh_height
       
        col = Column() 
        self.input_height = LabelInput('Height', self).append_to(col).input
        self.material = LabelInput('Material', self).append_to(col).input
        
        self.widget = Widget('Terrain', col, id='terrain').append_to(application.workspace)

        self.default_material = Texture(2, 2, GL_RGBA, data=(140, 140, 140, 255)*4)
        self.vertex_texture = Texture(width, height, GL_RGBA32F)
        self.normal_texture = Texture(application.width, application.height, GL_RGBA32F, unit=GL_TEXTURE0)

        self.vertex_fbo = Framebuffer(self.vertex_texture)
        self.normal_fbo = Framebuffer(self.normal_texture)

        self.update_vertex_shader = application.shader('update_vertex.frag')
        self.update_normals_shader = application.shader('update_normals.frag')
        self.update_normals_shader.vars.offsets = 1.0/application.width, 1.0/application.height

        self.reset_vertex = application.shader('reset_vertex.frag')
        self.reset_normals = application.shader('reset_normals.frag')
        self.vbo = self.generate_vbo(width, height)

        self.reset()
        self.updated = None

    def export_obj(self, filename):
        if not filename.endswith('.obj'):
            filename += '.obj'

        if self.input_height.source:
            heightmap = self.input_height.source.texture
            heightmap.retrieve()

            width, height = self.application.width, self.application.height

            with open(filename, 'w') as outfile:
                heights = map(lambda z: (z, float(z)/height), range(height))
                widths = map(lambda x: (x, float(x)/width), range(width))
                for iz, z in heights:
                    for ix, x in widths:
                        outfile.write('v %f %f %f\n' % (x, heightmap[ix, iz][0], z))

                self.normal_texture.retrieve()
                for normal in self.normal_texture:
                    outfile.write('vn %f %f %f\n' % tuple(normal[:3]))

                heights = map(lambda x: float(x)/height, range(height))
                widths = map(lambda y: float(y)/width, range(width))
                for y in heights:
                    for x in widths:
                        outfile.write('vt %f %f\n' % (x, y))
            
                i_width, i_height = width-1, height-1
                for z in range(i_height):
                    for x in range(i_width):
                        p1 = x+z*width
                        p2 = p1+width
                        p4 = p1+1
                        p3 = p2+1
                        outfile.write('f %i/%i/%i %i/%i/%i %i/%i/%i\n' % (
                            p1+1, p1+1, p1+1, p2+1, p2+1, p2+1, p3+1, p3+1, p3+1
                        ))
                        outfile.write('f %i/%i/%i %i/%i/%i %i/%i/%i\n' % (
                            p1+1, p1+1, p1+1, p3+1, p3+1, p3+1, p4+1, p4+1, p4+1
                        ))

    def export_float_array(self, filename):
        if not filename.endswith('.farr'):
            filename += '.farr'

        if self.input_height.source:
            heightmap = self.input_height.source.texture
            heightmap.retrieve()
            string = string_at(heightmap.buffer, heightmap.width*heightmap.height*4)
            with open(filename, 'wb') as outfile:
                outfile.write(string)

    def generate_vbo(self, width, height):
        #as an acceleration the arrays could be prefilled in C

        v4f = (c_float*(width*height*4))()
        width_factor, height_factor = 1.0/float(width), 1.0/float(height)
        for z in range(height):
            for x in range(width):
                offset = (x+z*width)*4
                v4f[offset:offset+4] = x*width_factor, 0, z*height_factor, 1

        i_width, i_height = width-1, height-1
        indices = (c_uint*(i_width*i_height*6))()
        for z in range(i_height):
            for x in range(i_width):
                offset = (x+z*i_width)*6
                p1 = x+z*width
                p2 = p1+width
                p4 = p1+1
                p3 = p2+1
                indices[offset:offset+6] = p1, p2, p3, p1, p3, p4

        return VertexObject(
            pbo                 = True,
            indices             = indices,
            dynamic_draw_v4f    = v4f,
        )

    def open(self, data, instances):
        offset = data['offset']
        self.widget.rect.x, self.widget.rect.y = offset['x'], offset['y']
        self.widget.layout()

        input_id = data['input_height']
        if input_id:
            node = instances[input_id]
            connect(node, self.input_height)
        
        material_id = data['material']
        if material_id:
            node = instances[material_id]
            connect(node, self.material)

    def reset(self):
        view = self.application.processing_view
        self.vertex_fbo.textures[0] = self.vertex_texture
        with nested(view, self.vertex_fbo, self.reset_vertex):
            quad(self.width, self.height)
            self.vbo.vertices.copy_from(self.vertex_texture)
        with nested(view, self.normal_fbo, self.reset_normals):
            quad(self.application.width, self.application.height)

    def update(self):
        view = self.application.processing_view
        revision = self.revision

        if self.material.source:
            self.material.source.update()

        if self.input_height.source:
            self.input_height.source.update()

        if revision != self.updated:
            self.application.ambient_occlusion.changed = True
            if self.input_height.source and self.input_height.source.complete:
                source = self.input_height.source.texture

                source.unit = GL_TEXTURE0
                
                self.vertex_fbo.textures[0] = self.vertex_texture
                with nested(view, self.vertex_fbo, source, self.update_vertex_shader):
                    quad(self.width, self.height)
                    self.vbo.vertices.copy_from(self.vertex_texture)

                with nested(view, self.normal_fbo, source, self.update_normals_shader):
                    quad(self.application.width, self.application.height)
            else:
                self.reset()
        
        self.application.ambient_occlusion.update()

        self.updated = revision

    def get_source(self):
        if self.input_height.source and self.input_height.source.complete:
            return self.input_height.source.texture

    @property
    def revision(self):
        if self.input_height.source:
            height = self.input_height.source.revision
        else:
            height = None

        if self.material.source:
            material = self.material.source.revision
        else:
            material = None

        return hash((height, material))
    
    def draw(self):
        glPushMatrix()
        glTranslatef(-0.5, 0, -0.5)
        self.normal_texture.unit = GL_TEXTURE0
        ambient_occlusion = self.application.ambient_occlusion.result
        ambient_occlusion.unit = GL_TEXTURE2

        if self.material.source and self.material.source.complete:
            self.material.source.texture.unit = GL_TEXTURE1
            with nested(self.normal_texture, self.material.source.texture, ambient_occlusion):
                self.vbo.draw(GL_TRIANGLES)
        else:
            self.default_material.unit = GL_TEXTURE1
            with nested(self.normal_texture, self.default_material, ambient_occlusion):
                self.vbo.draw(GL_TRIANGLES)
        glPopMatrix()
Example #7
0
class Terrain(object):
    id = 'terrain'

    def __init__(self, application):
        self.application = application
        self.width, self.height = width, height = application.mesh_width, application.mesh_height
       
        col = Column() 
        self.input_height = LabelInput('Height', self).append_to(col).input
        self.material = LabelInput('Material', self).append_to(col).input
        
        self.widget = Widget('Terrain', col, id='terrain').append_to(application.workspace)

        self.default_material = Texture(2, 2, GL_RGBA, data=(140, 140, 140, 255)*4)
        self.vertex_texture = Texture(width, height, GL_RGBA32F)
        self.normal_texture = Texture(application.width, application.height, GL_RGBA32F, unit=GL_TEXTURE0)

        self.vertex_fbo = Framebuffer(self.vertex_texture)
        self.normal_fbo = Framebuffer(self.normal_texture)

        self.update_vertex_shader = application.shader('update_vertex.frag')
        self.update_normals_shader = application.shader('update_normals.frag')
        self.update_normals_shader.vars.offsets = 1.0/application.width, 1.0/application.height

        self.reset_vertex = application.shader('reset_vertex.frag')
        self.reset_normals = application.shader('reset_normals.frag')
        self.vbo = self.generate_vbo(width, height)

        self.reset()
        self.updated = None

    def export_obj(self, filename):
        if not filename.endswith('.obj'):
            filename += '.obj'

        if self.input_height.source:
            heightmap = self.input_height.source.texture
            heightmap.retrieve()

            width, height = self.application.width, self.application.height

            with open(filename, 'w') as outfile:
                heights = map(lambda z: (z, float(z)/height), range(height))
                widths = map(lambda x: (x, float(x)/width), range(width))
                for iz, z in heights:
                    for ix, x in widths:
                        outfile.write('v %f %f %f\n' % (x, heightmap[ix, iz][0], z))

                self.normal_texture.retrieve()
                for normal in self.normal_texture:
                    outfile.write('vn %f %f %f\n' % tuple(normal[:3]))

                heights = map(lambda x: float(x)/height, range(height))
                widths = map(lambda y: float(y)/width, range(width))
                for y in heights:
                    for x in widths:
                        outfile.write('vt %f %f\n' % (x, y))
            
                i_width, i_height = width-1, height-1
                for z in range(i_height):
                    for x in range(i_width):
                        p1 = x+z*width
                        p2 = p1+width
                        p4 = p1+1
                        p3 = p2+1
                        outfile.write('f %i/%i/%i %i/%i/%i %i/%i/%i\n' % (
                            p1+1, p1+1, p1+1, p2+1, p2+1, p2+1, p3+1, p3+1, p3+1
                        ))
                        outfile.write('f %i/%i/%i %i/%i/%i %i/%i/%i\n' % (
                            p1+1, p1+1, p1+1, p3+1, p3+1, p3+1, p4+1, p4+1, p4+1
                        ))

    def export_float_array(self, filename):
        if not filename.endswith('.png'):
            filename += '.png'

        if self.input_height.source:
            heightmap = self.input_height.source.texture
            heightmap.retrieve()
            heightmap.save(filename)            
            #print(heightmap)
            #source = string_at(heightmap.buffer, sizeof(heightmap.buffer))
            #image = Image.frombytes("RGB", (self.width, self.height), source)
            #image.save(filename)

    def generate_vbo(self, width, height):
        #as an acceleration the arrays could be prefilled in C

        v4f = (c_float*(width*height*4))()
        width_factor, height_factor = 1.0/float(width), 1.0/float(height)
        for z in range(height):
            for x in range(width):
                offset = (x+z*width)*4
                v4f[offset:offset+4] = x*width_factor, 0, z*height_factor, 1

        i_width, i_height = width-1, height-1
        indices = (c_uint*(i_width*i_height*6))()
        for z in range(i_height):
            for x in range(i_width):
                offset = (x+z*i_width)*6
                p1 = x+z*width
                p2 = p1+width
                p4 = p1+1
                p3 = p2+1
                indices[offset:offset+6] = p1, p2, p3, p1, p3, p4

        return VertexObject(
            pbo                 = True,
            indices             = indices,
            dynamic_draw_v4f    = v4f,
        )

    def open(self, data, instances):
        offset = data['offset']
        self.widget.rect.x, self.widget.rect.y = offset['x'], offset['y']
        self.widget.layout()

        input_id = data['input_height']
        if input_id:
            node = instances[input_id]
            connect(node, self.input_height)
        
        material_id = data['material']
        if material_id:
            node = instances[material_id]
            connect(node, self.material)

    def reset(self):
        view = self.application.processing_view
        self.vertex_fbo.textures[0] = self.vertex_texture
        with nested(view, self.vertex_fbo, self.reset_vertex):
            quad(self.width, self.height)
            self.vbo.vertices.copy_from(self.vertex_texture)
        with nested(view, self.normal_fbo, self.reset_normals):
            quad(self.application.width, self.application.height)

    def update(self):
        view = self.application.processing_view
        revision = self.revision

        if self.material.source:
            self.material.source.update()

        if self.input_height.source:
            self.input_height.source.update()

        if revision != self.updated:
            if self.input_height.source and self.input_height.source.complete:
                source = self.input_height.source.texture
                source.unit = GL_TEXTURE0
                
                self.vertex_fbo.textures[0] = self.vertex_texture
                with nested(view, self.vertex_fbo, source, self.update_vertex_shader):
                    quad(self.width, self.height)
                    self.vbo.vertices.copy_from(self.vertex_texture)

                with nested(view, self.normal_fbo, source, self.update_normals_shader):
                    quad(self.application.width, self.application.height)
            else:
                self.reset()

        self.updated = revision

    @property
    def revision(self):
        if self.input_height.source:
            height = self.input_height.source.revision
        else:
            height = None

        if self.material.source:
            material = self.material.source.revision
        else:
            material = None

        return hash((height, material))
    
    def draw(self):
        glPushMatrix()
        glTranslatef(-0.5, 0, -0.5)
        self.normal_texture.unit = GL_TEXTURE0

        if self.material.source and self.material.source.complete:
            self.material.source.texture.unit = GL_TEXTURE1
            with nested(self.normal_texture, self.material.source.texture):
                self.vbo.draw(GL_TRIANGLES)
        else:
            self.default_material.unit = GL_TEXTURE1
            with nested(self.normal_texture, self.default_material):
                self.vbo.draw(GL_TRIANGLES)
        glPopMatrix()
Example #8
0
class Node(object):
    def __init__(self, label, application):
        self.application = application
        self.id = os.urandom(16).encode('hex')

        application.add_node(self)
        self.column = Column()
        bar_area = Area().add_class('widget_bar')
        Label(label).append_to(bar_area)
        Button().append_to(bar_area).on_click = self.delete
        self.texture = application.create_texture()
        self.widget = Widget(bar_area, self.column).add_class('node').append_to(application.workspace)
        self._parameters = {}
        self.sources = {}
        self.updated = None
        self.optional = []
    
    @property
    def revision(self):
        sources = tuple([input.source.revision if input.source else None for input in self.sources.values()])
        parameters = tuple((name, param.value) for name, param in self._parameters.items())
        return hash((self.__class__.__name__, parameters, sources))
    
    def get_parameters(self):
        return dict((name, param.value) for name, param in self._parameters.items())
    def set_parameters(self, values):
        for name, value in values.items():
            self._parameters[name].value = value

    parameters = property(get_parameters, set_parameters)
    del get_parameters, set_parameters

    @property
    def branch_nodes(self):
        nodes = set([self])
        for input in self.sources.values():
            if input.source:
                nodes |= input.source.branch_nodes
        return nodes

    def update_sources(self):
        for input in self.sources.values():
            if input.source:
                input.source.update()

    @property
    def complete(self):
        for name, input in self.sources.items():
            if name in self.optional:
                continue
            else:
                if input.source and input.source.complete:
                    continue 
                else:
                    return False

        return True

    def update(self):
        if self.complete:
            revision = self.revision
            self.update_sources()
            if revision != self.updated:
                self.compute()
            self.updated = revision 
    
    def reconnect(self, data, instances):
        for name, id in data.items():
            if id:
                instance = instances[id]
                input = self.sources[name]
                connect(instance, input)

    def delete(self):
        self.output.delete()
        self.texture.delete()
        for name, slot in self.sources.items():
            if slot.content:
                slot.content.delete()
                slot.content = None
            if slot.source:
                slot.source = None
        self.widget.remove()
        self.application.remove_node(self)
    
    def apply(self, shader, target, *sources):
        view = self.application.processing_view
        
        for i, source in enumerate(sources):
            source.unit = GL_TEXTURE0 + i

        fbo = self.application.framebuffer
        fbo.textures[0] = target

        with nested(view, fbo, shader, *sources):
            quad(target.width, target.height)
Example #9
0
class Node(object):
    def __init__(self, label, application):
        self.application = application
        self.id = os.urandom(16).encode('hex')

        application.add_node(self)
        self.column = Column()
        bar_area = Area().add_class('widget_bar')
        Label(label).append_to(bar_area)
        Button().append_to(bar_area).on_click = self.delete
        self.texture = application.create_texture()
        self.widget = Widget(bar_area,
                             self.column).add_class('node').append_to(
                                 application.workspace)
        self._parameters = {}
        self.sources = {}
        self.updated = None
        self.optional = []

    @property
    def revision(self):
        sources = tuple([
            input.source.revision if input.source else None
            for input in self.sources.values()
        ])
        parameters = tuple(
            (name, param.value) for name, param in self._parameters.items())
        return hash((self.__class__.__name__, parameters, sources))

    def get_parameters(self):
        return dict(
            (name, param.value) for name, param in self._parameters.items())

    def set_parameters(self, values):
        for name, value in values.items():
            self._parameters[name].value = value

    parameters = property(get_parameters, set_parameters)
    del get_parameters, set_parameters

    @property
    def branch_nodes(self):
        nodes = set([self])
        for input in self.sources.values():
            if input.source:
                nodes |= input.source.branch_nodes
        return nodes

    def update_sources(self):
        for input in self.sources.values():
            if input.source:
                input.source.update()

    @property
    def complete(self):
        for name, input in self.sources.items():
            if name in self.optional:
                continue
            else:
                if input.source and input.source.complete:
                    continue
                else:
                    return False

        return True

    def update(self):
        if self.complete:
            revision = self.revision
            self.update_sources()
            if revision != self.updated:
                self.compute()
            self.updated = revision

    def reconnect(self, data, instances):
        for name, id in data.items():
            if id:
                instance = instances[id]
                input = self.sources[name]
                connect(instance, input)

    def delete(self):
        self.output.delete()
        self.texture.delete()
        for name, slot in self.sources.items():
            if slot.content:
                slot.content.delete()
                slot.content = None
            if slot.source:
                slot.source = None
        self.widget.remove()
        self.application.remove_node(self)

    def apply(self, shader, target, *sources):
        view = self.application.processing_view

        for i, source in enumerate(sources):
            source.unit = GL_TEXTURE0 + i

        fbo = self.application.framebuffer
        fbo.textures[0] = target

        with nested(view, fbo, shader, *sources):
            quad(target.width, target.height)