Script dauerhaft laufen lassen

Blenders Funktionsumfang mit Python-Scripten erweitern.

Script dauerhaft laufen lassen

Beitragvon toyshung » 18.11.2016, 13:51

hallo,
was ist die beste möglichkeit in blender ein script dauerhaft im hintergrund laufen zu lassen? ich hab sowohl mit dem modal timer operator als auch schon mit threads rumprobiert, aber das scheint alles schnell an die grenzen zu kommen.
ich möchte im hintergrund eine tcp verbindung zu einem anderen pc oder dienst aufbauen und kontinuierlich daten hin und her schicken. habt ihr dafür eine gute lösung für mich?
danke und grüße
toyshung
 
Registriert:
01.11.2016, 10:40

Re: Script dauerhaft laufen lassen

Beitragvon HG1 » 19.11.2016, 23:21

Es sollte mit Modal funktionieren. Einmal aktiviert läuft es bis es wieder beendet wird.
Wo liegt das Problem bei dir mit Modal?
Eventuell liegt das Problem ja wo anders. Läuft der Client/Server in Blender auch in Non-Blocking Mode und ohne endlos Schleife.

Aber wenn die Modal nicht gefällt, dann kannst du noch scene_update_pre oder scene_update_post verwenden.
https://www.blender.org/api/blender_pyt ... dlers.html
HG1
 
Registriert:
16.08.2010, 11:43

Re: Script dauerhaft laufen lassen

Beitragvon toyshung » 19.11.2016, 23:34

ich habe ein script geschrieben, dass die vertexkoordinaten,texturekoordinaten, normals und indices an ein andres programm schickt. das ganze soll die ganze zeit im hintergrund laufen. allerdings fängt das ganze bei einer sphere mit knapp 500 vertices schon an zu ruckeln. und je komplexer das mesh ist desto mehr ruckelt das blender interface. ich habe gehofft, dass es eine möglichkeit gibt das ganze laufen zu lassen ohne, dass blender davon betroffen ist (um es mal ein wenig laienhaft zu sagen)

ich bin nicht der geborene programmierer und beschäftige mciht noch nciht so lange mit python muss ich dazu sagen.

hier mal mein aktueller code (vllt liegt der fehler ja woanders und hier kann mir jemand helfen):

Code: Alles auswählen
import bpy,bmesh,zmq,time,json,os
from bpy.types import Menu , Panel, UIList
clear = lambda: os.system('cls')


class MeshBuilder():
    def __init__(self,name):
        self.meshJson = {}
        self.meshname = name
        self.meshJson["Topic"] = "Mesh." + self.meshname
        self.obj = bpy.data.objects[self.meshname]
       


    def getAll(self):
        self.obj.update_from_editmode()
        bm = bmesh.new()
        bm.from_mesh(self.obj.data)
        bm.faces.ensure_lookup_table()
        bmesh.ops.split_edges(bm,edges=bm.edges,verts=bm.verts)
        uv_lay = bm.loops.layers.uv.active
        bmesh.ops.triangulate(bm,faces=bm.faces)
        vertcount = len(bm.verts)
        verts = [0] * vertcount
        uv_coords = [0] * vertcount
        indices = []
        normals = []
        for face in bm.faces:
            for loop in face.loops:
                verts[loop.vert.index] = tuple(self.obj.matrix_world * loop.vert.co)
                indices.append(loop.vert.index)
                normals.append(tuple(loop.calc_normal()))
                uv_coords[loop.vert.index] = tuple(loop[uv_lay].uv)
        self.meshJson["TextureCoords"] = [i[j] for i in uv_coords for j in range(len(i))]
        self.meshJson["Vertices"] = [i[j] for i in verts for j in range(len(i))]
        self.meshJson["Normals"] = [i[j] for i in normals for j in range(len(i))]
        self.meshJson["Indices"] = indices
        bm.free()


    #def run(self):
    #    self.meshJson["Vertices"],self.meshJson["Normals"],self.meshJson["TextureCoords"],self.meshJson["Indices"] = self.getAll()
    #    self.socket.send_json(self.getMesh())

    def getMesh(self):
        return self.meshJson

    def getMeshName(self):
        return self.meshname

class vvvvExport(bpy.types.Operator):
    bl_idname = "vvvv.start"
    bl_label = "Start"

    _timer = None
    _objects = []
    def modal(self, context, event):
        if event.type == 'INSERT':
            self.cancel(context)
            return {'CANCELLED'}

        if event.type == 'TIMER':
            for x in self._objects:
                x.getAll()
                mesh = x.getMesh()
                self.socket.send_json(mesh)
        return {'PASS_THROUGH'}

    def execute(self, context):
        self.zmqContext = zmq.Context()
        self.socket = self.zmqContext.socket(zmq.PAIR)
        self.socket.connect("tcp://localhost:4460")
        self._objects = [MeshBuilder(i.name) for i in bpy.context.selectable_objects]
        wm = context.window_manager
        self._timer = wm.event_timer_add(0.01, context.window)
        wm.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def cancel(self, context):
        wm = context.window_manager
        wm.event_timer_remove(self._timer)

def register():
    bpy.utils.register_class(vvvvExport)


def unregister():
    bpy.utils.unregister_class(vvvvExport)


if __name__ == "__main__":
    register()
    bpy.ops.vvvv.start()
toyshung
 
Registriert:
01.11.2016, 10:40

Re: Script dauerhaft laufen lassen

Beitragvon HG1 » 20.11.2016, 12:07

Na ja. Ich kann leider dein Script nicht testen aber wenn du keinen Fehler bekommst und du schreibst das es schon bei 500 Vertices zu ruckeln anfängt. Dann nehme ich mal an, dass es mit weniger funktioniert. Daraus folgere ich, dass an den vielen For-Schleifen liegt die du zyklisch aufrufst.
Alle Vertices zyklisch mit einer For-Schleife durchlaufen zu lassen ist natürlich nicht sehr performant. Blenders foreach_get ist da etwas schneller.
Code: Alles auswählen
me.vertices.foreach_get("co", verts)

Außerdem triangulierst und berechnest du die Normalen zyklisch. Besser wäre es wenn du die schon berechneten Daten des Meshes her nimmst. Am Besten du sieht dir den Code vom FBX Exporter an.

Es könnte auch an dem TCP Socket liegen, ist aber eher unwahrscheinlich da es ja nicht so viele Daten sind. Ich habe bis jetzt nicht mit zmq und Json gearbeitet, daher kann ich dazu auch nicht viel dazu sagen.
Um dies zu testen generiere die Meshdaten nur ein mal und sende dann anschließend die Daten kontinuierlich. Falls hier schon ein Performance-Einbuch zu spüren ist, musst du auf UDP wechseln.
HG1
 
Registriert:
16.08.2010, 11:43

Re: Script dauerhaft laufen lassen

Beitragvon toyshung » 21.11.2016, 12:54

wie komme ich an normals,texcoords und vor allem die richtige indice reihenfolge wenn ich nicht mit einer for schleife über die flächen iteriere?

die foreach funkton kannte ich noch nicht. das problem dabei ist, dass ich einfach nur eine liste mit den koordinaten bekomme, diese aber dann nicht mehr in die worldkoordinaten umrechnen kann weil es keine vektoren sind. korrigier mich bitte wenn ich falsch liege.

danke für deine hilfe :thumbup:
toyshung
 
Registriert:
01.11.2016, 10:40

Re: Script dauerhaft laufen lassen

Beitragvon HG1 » 21.11.2016, 20:41

das problem dabei ist, dass ich einfach nur eine liste mit den koordinaten bekomme, diese aber dann nicht mehr in die worldkoordinaten umrechnen kann weil es keine vektoren sind. korrigier mich bitte wenn ich falsch liege.

Foreach_get macht nur eine Flache Sequenz (kontinuierliche Reihenfolge). Das heißt der erste Wert entspricht X der Zweite Y der Dritte Z, dann wieder XYZ usw. Bei UV ist es dann xyxy usw.
https://www.blender.org/api/blender_pyt ... oreach_get
Du kannst aus der Flachen Sequenz wieder in Slices aufteilen ( sliced = (zip(*[iter(Sequenz)]*3)) ) aber ich würde bezüglich der Performance darauf verzichten.

Im Normalfall werden die Vertices von einem Objekt von ja immer mit Objektorientierten gespeichert bzw. exportiert. Zusätzlich wird dann noch zu jedem Objekt die Rotation und Position gespeichert. Die Objekte gleich mit Weltkoordinaten auszugeben ist eher ungewöhnlich.
Aber das musst du ja entscheiden wie du die Daten vorliegen haben möchtest (ich kann ja nicht wissen was genau du vor hast).
Du kannst ja auch deine For Schleifen für dein Bmesh durch foreach_get() ersetzen.

Bezüglich der anderen Werte wie Normals, Texcoords usw. findest du alles im FBX Exporter,
wie ich schon geschrieben habe.
...\Blender\2.78\scripts\addons\io_scene_fbx\export_fbx.py
me.loops.foreach_get("vertex_index", t_vi)
me.polygons.foreach_get("loop_start", t_ls)
uvlayer.data.foreach_get("uv", t_uv)
me.loops.foreach_get("normal", t_vn)
HG1
 
Registriert:
16.08.2010, 11:43


Zurück zu Blender Python


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 2 Gäste

cron