Revision 1fdee286

View differences:

plugin_blender/__init__.py
1
bl_info = {
2
    "author": "Jonas Diekmann",
3
    "name": "Marker Tracker Plugin",
4
    "description": "Tools for BA-Thesis",
5
    "warning": "",
6
    "version": (0, 11, 3),
7
    "blender": (2, 72, 0),
8
    "support": "TESTING",
9
    "category": "Add Mesh"
10
}
11
# Dies ist die Hauptdatei des Plugins
12
# Sie wird geladen, wenn das Plugin geladen wird.
13
# Normalerweise geschieht dies beim Start von Blender
14
# Es ist aber auch möglich diese datei direkt zu laden.
15
# Aufgabe dieser Datei ist es alle anderen teile des 
16
# Plugins nachzuladen.
17
### Der untestehende Code (bis ###) basiert auf [3].
18

  
19
# Lädt die Dateien neu, wenn das Plugin aufgefrischt werden soll.
20
if "bpy" in locals():
21
    import imp
22
    if "view" in locals():
23
        imp.reload(view)
24
    else:
25
        print("Datei view.py fehlt!");
26
    if "adjust" in locals():
27
        imp.reload(adjust)
28
    else:
29
        print("Datei adjust.py fehlt!");
30
    if "controller" in locals():
31
        imp.reload(controller)
32
    else:
33
        print("Datei controller.py fehlt!");
34
    if "model" in locals():
35
        imp.reload(model)
36
    else:
37
        print("Datei model.py fehlt!");
38
    if "switch_texture" in locals():
39
        imp.reload(switch_texture)
40
    else:
41
        print("Datei switch_texture.py fehlt!");
42
    if "tools" in locals():
43
        imp.reload(tools)
44
    else:
45
        print("Datei tools.py fehlt!");
46
    print("Pakete aufgefrischt")
47
else:
48
    # Importiert die übrigen Module, wenn das Plugin (oder eigentlich bpy)
49
    # noch nicht geladen war.
50
    from .view           import GraphischeOberflaeche
51
    from .adjust         import KameraJustieren, FormatEinstellen, EinheitenEinstellen
52
    from .controller     import PositionenAusgeben, MarkerHinzufuegen, MarkerRandomisieren #,EulerwinkelAusgeben
53
    from .model          import Plugineigenschaften
54
    from .switch         import WechsleBibliothek, WechsleZuBART, WechsleZuALVAR
55
    from .tools          import Import1, Import2
56
    print("Pakete importiert")
57
###
58

  
59
import bpy
60

  
61
# Registriert alle Klassen des Plugins
62
def register():
63
    bpy.utils.register_class(Plugineigenschaften)
64
    bpy.types.Scene.markerRender = bpy.props.PointerProperty(type=Plugineigenschaften)
65
    bpy.types.Object.marker_id = bpy.props.IntProperty(default=-1,min=-1)
66
    bpy.types.ImageTexture.library = bpy.props.StringProperty(name="library",default='BART',maxlen=100)
67
    bpy.types.ImageTexture.marker_id = bpy.props.IntProperty(default=-1,min=-1)
68
    bpy.utils.register_class(PositionenAusgeben)
69
    bpy.utils.register_class(MarkerHinzufuegen)
70
    #bpy.utils.register_class(EulerwinkelAusgeben)
71
    bpy.utils.register_class(MarkerRandomisieren)
72
    bpy.utils.register_class(WechsleBibliothek)
73
    bpy.utils.register_class(WechsleZuBART)
74
    bpy.utils.register_class(WechsleZuALVAR)
75
    bpy.utils.register_class(EinheitenEinstellen)
76
    bpy.utils.register_class(KameraJustieren)
77
    bpy.utils.register_class(FormatEinstellen)
78
    bpy.utils.register_class(GraphischeOberflaeche)
79
    bpy.utils.register_class(Import1)
80
    bpy.utils.register_class(Import2)
81

  
82
# Macht die Registrierung aller Klassen des Plugins rückgängig.
83
def unregister():
84
    bpy.utils.unregister_class(Import2)
85
    bpy.utils.unregister_class(Import1)
86
    bpy.utils.unregister_class(GraphischeOberflaeche)
87
    bpy.utils.unregister_class(MarkerRandomisieren)  
88
    bpy.utils.unregister_class(FormatEinstellen)
89
    bpy.utils.unregister_class(KameraJustieren)
90
    bpy.utils.unregister_class(EinheitenEinstellen)
91
    bpy.utils.unregister_class(WechsleZuALVAR)
92
    bpy.utils.unregister_class(WechsleZuBART)
93
    bpy.utils.unregister_class(WechsleBibliothek)
94
    #bpy.utils.unregister_class(EulerwinkelAusgeben)
95
    bpy.utils.unregister_class(MarkerHinzufuegen)
96
    bpy.utils.unregister_class(PositionenAusgeben)  
97
    bpy.utils.unregister_class(Plugineigenschaften) 
98

  
99
# Dies ist der Einsprungspunkt, falls das Skript über
100
# die entsprechende Schaltfläche in Blender ausgeführt wird.
101
if __name__ == "__main__":
102
    register()
103
    
104
# Quellen:
105
#  0  API: http://www.blender.org/api/blender_python_api_2_72_release
106
#  1  PYTHON kurz & gut:
107
#  2  Quickstart: http://www.blender.org/api/blender_python_api_2_72_release/info_quickstart.html
108
#  3  Multi-file packages: http://wiki.blender.org/index.php/Dev:2.5/Py/Scripts/Cookbook/Code_snippets/Multi-File_packages
109
#
110
# Tipp: Der Tooltip der meisten Felder nennt den Pfad der Eigenschaft.
111
#       Operatoren werden zudem im Infofenster protokolliert.
112
#       Dadurch kann man manchmal die gewünschten Aktionen über die GUI durchführen und die Befehle kopieren. (vgl. auch http://www.blender.org/api/blender_python_api_2_72_release/info_api_reference.html#copy-data-path)
113
 
plugin_blender/adjust.py
1
import bpy
2

  
3

  
4

  
5

  
6

  
7

  
8

  
9

  
10
class KameraJustieren(bpy.types.Operator):
11
    """Stellt die Kamera auf die für die Kalibrierung verwendeten Werte ein """
12
    bl_idname = "camera.adjust_camera"
13
    bl_label = "Kamera justieren"
14

  
15
    # Wird ausgeführt um zu testen, ob die Operation des Operators möglich ist.
16
    @classmethod
17
    def poll(cls, context):
18
        return (bpy.context.scene.markerRender.kameraDatenID in bpy.data.cameras.keys())
19
   
20
    # Stellt die Kamera auf die für die Kalibrierung verwendeten Werte ein
21
    def execute(self, context):
22
        kameraID = bpy.context.scene.markerRender.kameraDatenID
23
        bpy.data.cameras[kameraID].angle_x = 0.8575560450553894
24
        bpy.data.cameras[kameraID].angle_y = 0.5033799409866333
25
        bpy.data.cameras[kameraID].clip_end = 20.0
26
        bpy.data.cameras[kameraID].clip_start = 0.10000000149011612
27
        bpy.data.cameras[kameraID].sensor_fit = 'AUTO'
28
        bpy.data.cameras[kameraID].sensor_height = 18.0
29
        bpy.data.cameras[kameraID].sensor_width = 32.0
30
        bpy.data.cameras[kameraID].shift_x = 0.0
31
        bpy.data.cameras[kameraID].shift_y = 0.0
32
        bpy.data.cameras[kameraID].dof_distance = 7.929999828338623
33
        return {'FINISHED'}
34
    
35
class EinheitenEinstellen(bpy.types.Operator):
36
    """Stellt das Einheitensystem ein"""
37
    bl_idname = "scene.adjust_units"
38
    bl_label = "Einheiten einstellen"
39

  
40
    # Wird ausgeführt um zu testen, ob die Operation des Operators möglich ist.
41
    @classmethod
42
    def poll(cls, context):
43
        return True
44

  
45
    # Stellt das Einheitensystem ein
46
    def execute(self, context):
47
        bpy.context.scene.unit_settings.system = "METRIC"
48
        return {'FINISHED'}
49
    
50
class FormatEinstellen(bpy.types.Operator):
51
    """Stellt das Ausgabeformat ein (Auflösung, Dateiformat etc.)"""
52
    bl_idname = "render.adjust_dimensions"
53
    bl_label = "Format einstellen"
54

  
55
    # Wird ausgeführt um zu testen, ob die Operation des Operators möglich ist.
56
    @classmethod
57
    def poll(cls, context):
58
        return True
59

  
60
    # Stellt das Ausgabeformat ein (Auflösung, Dateiformat etc.)
61
    def execute(self, context):
62
        ### Der folgende Codeabschnitt (bis zum nächsten ### ) wurde mit bpy.ops.render.preset_add() erzeugt
63
        szene = bpy.context.scene
64
        szene.render.field_order = 'EVEN_FIRST'
65
        szene.render.fps = 48
66
        szene.render.fps_base = 1.0
67
        szene.render.pixel_aspect_x = 1.0
68
        szene.render.pixel_aspect_y = 1.0
69
        szene.render.resolution_percentage = 100
70
        szene.render.resolution_x = 1920
71
        szene.render.resolution_y = 1080
72
        szene.render.use_fields = False
73
        szene.render.use_fields_still = False
74
        ###
75
        bpy.data.scenes['Scene'].render.image_settings.file_format = "JPEG"
76
        bpy.data.scenes['Scene'].render.image_settings.quality = 100
77
        return {'FINISHED'}
plugin_blender/controller.py
1
import bpy
2
from math import sqrt 
3
import random       
4

  
5

  
6

  
7

  
8
class PositionenAusgeben(bpy.types.Operator):
9
    """Gibt die Distanz, Orientierung und Position im Koordinatensystem der Kamera aus"""
10
    bl_idname = "print_object.position"
11
    bl_label = "Position ausgeben"
12
    
13
    # Wird ausgeführt um zu testen, ob die Operation des Operators möglich ist.
14
    @classmethod
15
    def poll(cls, context):
16
        return ((bpy.context.scene.markerRender.kameraID in bpy.context.scene.objects.keys()) and (bpy.context.scene.markerRender.markerID in bpy.context.scene.objects.keys() or bpy.context.scene.markerRender.markerID == "") and (bpy.context.scene.markerRender.dateipfad != ""))
17
    
18
    # Gibt die Distanz, Orientierung und Position im Koordinatensystem der Kamera aus
19
    def execute(self, context):
20
        model = bpy.context.scene.markerRender
21
        dateipfad = bpy.path.abspath(model.dateipfad)
22
        ausgabedatei= open(bpy.path.ensure_ext(dateipfad,".txt"),mode='w')
23
        csvAusgabe= open(bpy.path.ensure_ext(dateipfad,".csv"),mode='w')
24
        bildnummer = 0
25
        bpy.context.scene.frame_current = bpy.context.scene.frame_start
26
        while(bildnummer <=  (bpy.context.scene.frame_end/bpy.context.scene.frame_step)):
27
            bpy.context.scene.frame_set(bpy.context.scene.frame_start + bildnummer * bpy.context.scene.frame_step)
28
            self.bildVerarbeiten(context,csvAusgabe,ausgabedatei,(bildnummer+1))
29
            bildnummer += 1
30
        ausgabedatei.flush()
31
        ausgabedatei.close()
32
        csvAusgabe.flush()
33
        csvAusgabe.close()
34
        print("Positionen nach",bpy.path.ensure_ext(dateipfad,".txt"),"und",bpy.path.ensure_ext(dateipfad,".csv"),"ausgegeben")
35
        return {'FINISHED'}
36
        
37
    # Wird für jedes Bild einmal ausgeführt    
38
    def bildVerarbeiten(self, context, csvAusgabe, ausgabedatei, bildnummer):
39
        model = bpy.context.scene.markerRender
40
        kamera = context.scene.objects[model.kameraID]
41
        
42
        print("Bild",(bildnummer-1),file=ausgabedatei)
43
        print(" Kamera Position: (",end="",file=ausgabedatei)
44
        print(kamera.location.x, kamera.location.y, kamera.location.z,sep=",",end="",file=ausgabedatei)
45
        print(")",file=ausgabedatei)
46
        
47
        if(model.markerID == ""):
48
            zaehler = 0
49
            zuEntfernen = []
50
            for id in model.markerIDs:
51
                if(id.value in context.scene.objects.keys()):    
52
                    object = context.scene.objects[id.value]
53
                    if(not object.hide_render):
54
                        self.markerVerarbeiten(object,kamera,ausgabedatei,csvAusgabe,model,bildnummer)
55
                        zaehler += 1
56
                else:
57
                    print("INFO: Vermisse "+id.value+" in "+str(context.scene.objects.keys()))
58
                    zuEntfernen.append(zaehler)
59
            # Überflüssige Schlüssel entfernen
60
            for schluessel in zuEntfernen:   
61
                model.markerIDs.remove(schluessel)
62
        else: 
63
            object = context.scene.objects[model.markerID]
64
            self.markerVerarbeiten(object,kamera,ausgabedatei,csvAusgabe,model)
65
            
66
    def achsendatenAusgeben(self, dist,object,csvAusgabe):
67
        print(dist,sep=",",file=csvAusgabe)
68
        
69
    # wird für jeden Marker ausgeführt
70
    def markerVerarbeiten(self, object, kamera, ausgabedatei, csvAusgabe, model, bildnummer):
71
        dist = distanz(object.location.x,object.location.y,object.location.z,kamera.location.x,kamera.location.y,kamera.location.z)
72
        
73
        print(" ",object.name,"Position: (",end="",file=ausgabedatei)
74
        print(object.location.x, object.location.y, object.location.z,sep=",",end="",file=ausgabedatei)
75
        print(")",file=ausgabedatei)
76
        print(" ",object.name,"Distanz:",end=" ",file=ausgabedatei)
77
        print(dist,sep=",",file=ausgabedatei)
78
        
79
        #Testet, ob es einen einfachen Weg gibt an die Transformationsmatrix zwischen kamera und Objekt zu gelangen
80
        if(object.parent != None and object.parent == kamera):
81
            matrix = object.matrix_local 
82
        elif(object.parent != None and object.parent.parent != None and object.parent.parent == kamera):
83
            matrix = object.parent.matrix_local*object.matrix_local
84
        else:
85
            #Es gibt keinen einfachen Weg :(
86
            print("Warnung: Invertierte globale Matritzen verwendet. Das ist weniger genau. Überlege, ob die Marker Kinder der Kamera oder eines ihrer direkten Kinder werden können.")
87
            print("Warnung: Invertierte globale Matritzen verwendet. Das ist weniger genau. Überlege, ob die Marker Kinder der Kamera oder eines ihrer direkten Kinder werden können.",file=ausgabedatei)
88
            matrix = kamera.matrix_world.inverted_safe()*object.matrix_world
89
        
90
        #An diesem Punkt enthält matrix die Transformationsmatrix zwischen Marker und Kamera
91
         
92
        # Gibt nach und nach die Bildnummer, die Markerid, die Rotationsmatrix, den Translationsvektor usw. aus
93
        if(matrix != None):    
94
            print(" ",object.name,"Transformation bezüglich der Kamera:",file=ausgabedatei)
95
            if(object.marker_id != None):
96
                print(bildnummer,object.marker_id,sep=",",end=",",file=csvAusgabe)
97
            else:
98
                print(bildnummer,-1.0,sep=",",file=csvAusgabe)
99
            spalte = 0
100
            while(spalte < len(matrix[0])):
101
               line = 0
102
               print("   ",end="",file=ausgabedatei)
103
               while(line < len(matrix)):
104
                   print(matrix[line][spalte],end=", ",file=ausgabedatei)
105
                   if(not ((line%4) == 3)):
106
                       print(matrix[line][spalte],end=",",file=csvAusgabe)
107
                   line += 1
108
               print("",file=ausgabedatei)
109
               spalte += 1
110
            print("",file=ausgabedatei)
111
            print(matrix[3][3],end=",",file=csvAusgabe)
112
            self.achsendatenAusgeben(dist, object, csvAusgabe)
113
            
114

  
115
#class EulerwinkelAusgeben(PositionenAusgeben):
116
 #   """Gibt auch die Eulerwinkel für Achsenbeschriftungen aus"""
117
  #  bl_idname = "print_object.rotation"
118
   # bl_label = "Include Rotation"
119
    #
120
    #def achsendatenAusgeben(self,dist,object,csvAusgabe):
121
     #   euler = object.rotation_euler
122
      #  print(dist,euler.x,euler.y,euler.z,sep=",",file=csvAusgabe)
123
   
124
        
125
class MarkerHinzufuegen(bpy.types.Operator):
126
    """Erzeugt ein neues flaches Objekt fügt es der Szene hinzu und versieht es mit entsprechenden Texturen und Attributen"""
127
    bl_idname = "mesh.primitive_marker_add"
128
    bl_label  = "Marker hinzufügen"
129
    
130
    # Wird ausgeführt um zu testen, ob die Operation des Operators möglich ist.
131
    @classmethod
132
    def poll(cls, context):
133
        return context.mode == "OBJECT"
134

  
135
    # Wird ausgeführt, um einen neuen Marker hinzuzufügen
136
    def execute(self, context):
137
        markerID = str (bpy.context.scene.markerRender.newMarkerID)
138
        bpy.ops.object.select_all(action="DESELECT")
139
        
140
        markerIDSuffix = ""
141
        zaehler = 1
142
        while("Marker_"+markerID+markerIDSuffix in bpy.data.objects.keys()):
143
            markerIDSuffix = ".0"+str (zaehler)
144
            zaehler += 1
145
        
146
        #Erstellt Mesh
147
        bpy.ops.mesh.primitive_cube_add(radius=0.5)
148
        context.selected_objects[0].name = "Marker_"+markerID+markerIDSuffix
149
        bildschirm = context.screen
150
        gliederungGefunden = False
151
        for bereich in bildschirm.areas:
152
            if bereich.type == 'OUTLINER':
153
                gliederungGefunden = True
154
                kontextUeberschreiben = {'screen': bildschirm, 'area': bereich}
155
                bpy.ops.outliner.parent_drop(kontextUeberschreiben,child=context.selected_objects[0].name, parent=bpy.context.scene.markerRender.kameraID)
156
                break 
157
        if(not gliederungGefunden):
158
            print("Skipped reparenting. Please activate Outliner!")
159

  
160
        context.selected_objects[0].scale[2] = 0.005
161
        plane = context.selected_objects[0].data
162
        bpy.data.objects["Marker_"+markerID+markerIDSuffix].marker_id = bpy.context.scene.markerRender.newMarkerID
163
        
164
        #Erstellt Material
165
        bpy.ops.material.new()
166
        material = bpy.data.materials[-1]
167
        bpy.data.materials[-1].name = "Marker_"+markerID+markerIDSuffix
168
        
169
        
170
        #Erstellt Texturen
171
        material = createTexture(markerID,bpy.context.scene.markerRender.kontrastErhoehen,"//BART_Marker/","Marker","BART_Marker_",'BART',material)
172
        material = createTexture(markerID,bpy.context.scene.markerRender.kontrastErhoehen,"//ALVAR_Marker/","MarkerData_","ALVAR_Marker_",'ALVAR',material)
173
        
174
        #Weist Material zu
175
        plane.materials.append(material)
176
        
177
        #In Liste einhängen
178
        knoten       = bpy.context.scene.markerRender.markerIDs.add()
179
        knoten.value = "Marker_"+markerID+markerIDSuffix
180
        
181
        #Unwrap (nur der obenliegenden Seite)
182
        bpy.ops.object.editmode_toggle()
183
        bpy.ops.mesh.select_all(action="DESELECT")
184
        bpy.ops.object.editmode_toggle() 
185
        bpy.data.objects["Marker_"+markerID+markerIDSuffix].data.polygons[5].select = True
186
        bpy.ops.object.editmode_toggle() 
187
        bpy.ops.uv.unwrap()
188
        bpy.ops.object.editmode_toggle() 
189
        
190
        if(bpy.context.scene.markerRender.incrementNewMarkerID):
191
            bpy.context.scene.markerRender.newMarkerID+=1
192
        return {'FINISHED'}
193
    
194
class MarkerRandomisieren(bpy.types.Operator):
195
    """Randomisiert die Markerid des ausgewählten Markers"""
196
    bl_idname = "mesh.randomize_marker"
197
    bl_label  = "Marker randomisieren"
198
    
199
    # Wird ausgeführt um zu testen, ob die Operation des Operators möglich ist.
200
    @classmethod
201
    def poll(self,context):
202
        
203
        return True #context.object.marker_id > -1
204
    
205
    def execute(self, context):
206
        ursprungsbild = context.scene.frame_current
207
        #Fange beim ersten Frame an
208
        context.scene.frame_current = 1
209
        
210
        #Suche nach einem geeigneten Material
211
        object = context.object
212
        original_id = object.marker_id
213
        object.keyframe_insert("marker_id",frame=1)
214
        material_index = object.material_slots.find("Marker_"+str(original_id))
215
        if(material_index == -1):
216
            # Die ID wurde leider verändert! Suche Material.
217
            # Da der Marker nur wenige Materialien enthalten dürften, sollte dieser Test schnell sein.
218
            material = None
219
            for material_slot in object.material_slots:
220
                for texture_slot in material_slot.material.texture_slots:
221
                    if (texture_slot != None and texture_slot.texture.marker_id > -1):
222
                        material = material_slot.material
223
                        print("Warning: Using",material.name)
224
                        break
225
            if(material == None):
226
                print("Could not randomise marker. Unable to find appropriate material.")
227
                return {'CANCELLED'} 
228
        else:
229
            material = object.material_slots[material_index].material
230
        material.keyframe_insert("use_textures",options={'INSERTKEY_NEEDED'})
231
            
232
        #Finde einen unbenutzten Slot
233
        material.active_texture_index = len(context.object.active_material.texture_slots.keys())
234
        id = -1
235
        usedids = []
236
        while (context.scene.frame_current < context.scene.frame_end and material.active_texture_index < 17) :
237
            id = random.randint(original_id-50,original_id+50)
238
            if(id < 0):
239
                id += 50
240
            elif(id > 1000):
241
                id %= 1000
242

  
243
            if(id in usedids):
244
                #Die ids sollen einmalig sein, um die Streuung möglichst groß zu halten
245
                #und den Programmieraufwand beim Wechseln der Texturen zu verringern
246
                continue
247
            usedids.append(id)
248
            object.marker_id = id
249
            object.keyframe_insert("marker_id")
250
            #Workaround um zu verhindern, dass zwischen den IDs interpoliert wird
251
            object.keyframe_insert("marker_id",frame=context.scene.frame_current+1)
252
            object.keyframe_insert("marker_id",frame=context.scene.frame_current+2)
253
            object.keyframe_insert("marker_id",frame=context.scene.frame_current+3)
254
            
255
            #XXX Mit den Schlüsseln arbeiten, da Werte sonst nicht übernommen werden (keine reguläre Liste)
256
            for schluessel in range(0,len(material.use_textures)):
257
                material.use_textures[schluessel] = False
258
            
259
            # Die Textur für BART erstellen
260
            material = createTexture(str(id),False,"//BART_Marker/","Marker","BART_Marker_",'BART',material)
261
            material.use_textures[material.active_texture_index-1] = True 
262
            
263
            # Die Textur für ALVAR erstellen
264
            material = createTexture(str(id),False,"//ALVAR_Marker/","MarkerData_","ALVAR_Marker_",'ALVAR',material)
265
            material.use_textures[material.active_texture_index-1] = True 
266

  
267
            #Nach Erreichen von 17 wird nicht weiter hochgezählt, wir haben also erneut die Textur an Position 16 aktiviert und müssen das für 17 noch einmal erledigen.
268
            if(material.active_texture_index == 17):
269
                material.use_textures[17] = True
270
            material.keyframe_insert("use_textures",frame=context.scene.frame_current,options={'INSERTKEY_NEEDED'})
271
            context.scene.frame_current += 4
272
            print(id)
273
        
274
        #Mehr Texturen sind leider nicht erlaubt. Mische zwischen den vorhandenen Texturen.
275
        while(context.scene.frame_current < context.scene.frame_end):
276
            # Finde die Indizes für BART und erstelle ein Wörterbuch, das den Markernummern die Indizes von ALVAR zuordnet
277
            texturenBART = [ i for i in range(0,17) if material.texture_slots[i].texture.library == 'BART' and material.texture_slots[i].texture.marker_id != id]
278
            texturenALVAR = { material.texture_slots[i].texture.marker_id:i for i in range(0,17) if material.texture_slots[i].texture.library == 'ALVAR' and material.texture_slots[i].texture.marker_id != id}
279
            #Zufällige Reihenfolge herstellen
280
            random.shuffle(texturenBART)
281
            index = 0
282
            while (context.scene.frame_current < context.scene.frame_end and index < len(texturenBART) and index < len(texturenALVAR)) :
283
                #XXX Mit den Schlüsseln arbeiten, da Werte sonst nicht übernommen werden (keine reguläre Liste)
284
                # Nicht benötigte Texturen deaktivieren
285
                for schluessel in range(0,len(material.use_textures)):
286
                    material.use_textures[schluessel] = False
287
                slot_index = texturenBART[index]
288
                # Die ausgeloste Textur beider Bibliotheken aktivieren 
289
                id =  material.texture_slots[ slot_index ].texture.marker_id
290
                if(id in texturenALVAR):
291
                    material.use_textures[ slot_index ] = True 
292
                    material.use_textures[ texturenALVAR[id] ] = True
293
                    object.marker_id = id
294
                    object.keyframe_insert("marker_id",frame=context.scene.frame_current)
295
                    
296
                    # Workaround um zu verhindern, dass zwischen den IDs der Schlüsselbilder Interpoliert wird
297
                    object.keyframe_insert("marker_id",frame=context.scene.frame_current+1)
298
                    object.keyframe_insert("marker_id",frame=context.scene.frame_current+2)
299
                    object.keyframe_insert("marker_id",frame=context.scene.frame_current+3)
300
                    material.keyframe_insert("use_textures",frame=context.scene.frame_current,options={'INSERTKEY_NEEDED'})
301
                    print(context.scene.frame_current,object.marker_id,material.texture_slots[ slot_index ].texture.name, material.texture_slots[ slot_index ].name)
302
                else:
303
                    print("Warnung: Id",id,"wurde nicht für BART und ALVAR gefunden. Ich wähle eine andere.")
304
                    index += 1
305
                    continue
306
                
307
                # Springe zum nächsten Schlüsselbild
308
                context.scene.frame_current += 4
309
                index += 1
310
            
311
        context.scene.frame_current = ursprungsbild    
312
        return {'FINISHED'}
313
    
314
    
315
# Hilfsfunktionen
316

  
317
# Erzeugt eine Textur, für einen Marker mit der übergebenen markerID und den übergebenen Eigenschaften
318
def createTexture(markerID,kontrastErhoehen,dateipfad,dateiPrefix,idPrefix,bibliotheksID,material):
319
    if(kontrastErhoehen):
320
        idSuffix = "hC"
321
    else:
322
        idSuffix = ""
323
    if(not (idPrefix+markerID+idSuffix in bpy.data.textures.keys())):
324
        # Erstellt Textur
325
        bpy.ops.texture.new()
326
        bpy.data.textures[-1].name = idPrefix+markerID+idSuffix
327
        bpy.data.textures[idPrefix+markerID+idSuffix].type = 'IMAGE'
328
        bpy.ops.image.open(filepath=dateipfad+dateiPrefix+markerID+".png")
329
        
330
        # Sorgt für eindeutige Identifikation, für den Fall das der Benutzer bzw. die Benutzerin Texturen und Bilder verschiebt und/oder umbenennt
331
        bpy.data.textures[idPrefix+markerID+idSuffix].library = bibliotheksID
332
        bpy.data.textures[idPrefix+markerID+idSuffix].marker_id = int(markerID)
333
        
334
        bpy.data.textures[idPrefix+markerID+idSuffix].image = bpy.data.images[dateiPrefix+markerID+".png"]
335
        if(kontrastErhoehen):
336
            # Erhöht den Kontrast
337
            bpy.data.textures[idPrefix+markerID+idSuffix].intensity = 2
338
            bpy.data.textures[idPrefix+markerID+idSuffix].contrast = 3
339
    
340
    # Weist die Standard-UV-Map zu        
341
    material.active_texture   = bpy.data.textures[idPrefix+markerID+idSuffix]
342
    material.texture_slots[material.active_texture_index].texture_coords   = 'UV'
343
    material.texture_slots[material.active_texture_index].uv_layer = 'UVMap'
344
    material.active_texture_index+=1
345
    return material
346

  
347
# Berechnet den Abstand zweier Punkte 1 und 2 
348
def distanz(x1,y1,z1,x2,y2,z2):
349
    return laenge(x1-x2,y1-y2,z1-z2)
350

  
351
# Berechnet die Länge eines Vektors
352
def laenge(x,y,z):
353
    return sqrt(x*x+y*y+z*z)
354

  
plugin_blender/model.py
1
import bpy
2

  
3

  
4

  
5
class Plugineigenschaften(bpy.types.PropertyGroup):
6
    """Enthält die von diesem Plugin verwendeten Daten"""
7
    kameraID             = bpy.props.StringProperty(name="kameraID",description="Die ID der zu verwendenden Kamera")
8
    kameraDatenID        = bpy.props.StringProperty(name="kameraDatenID",description="Die ID des zu der Kamera gehörenden Datenblockes")
9
    markerID             = bpy.props.StringProperty(name="markerID",description="Die (Blender-)ID des zu trackenden Markers. Bei einem leeren Feld werden alle Marker verwendet.")
10
    dateipfad             = bpy.props.StringProperty(subtype="FILE_PATH")
11
    newMarkerID          = bpy.props.IntProperty(min=0,soft_min=0,max=1000)
12
    incrementNewMarkerID = bpy.props.BoolProperty(description="Markernummer nach der Erzeugung erhöhen")
13
    kontrastErhoehen     = bpy.props.BoolProperty(description="Kontrast und Helligkeit des Markers erhöhen")
14
    markerIDs            = bpy.props.CollectionProperty(type=bpy.types.NodeSetting)
15

  
plugin_blender/switch.py
1
import bpy
2

  
3
class WechsleBibliothek(bpy.types.Operator):
4
    """Oberklasse aller Klassen für Texturwechsel"""
5
    bl_idname = "texture.to_library"
6
    bl_label  = "LIBRARY"
7
    
8
    # Wird ausgeführt um zu testen, ob die Operation des Operators möglich ist.
9
    @classmethod
10
    def poll(cls,context):
11
        return context.mode == "OBJECT"
12
    
13
    # Wird ausgeführt um die Textur zu wechseln
14
    def execute(self,context):
15
        model = bpy.context.scene.markerRender
16
        zaehler = 0
17
        zuEntfernen = []
18
        #Schleife über alle Marker
19
        for id in model.markerIDs:
20
            if(id.value in context.scene.objects.keys()):    
21
                marker = context.scene.objects[id.value]
22
                self.markerVerarbeiten(context,marker,model)
23
                zaehler += 1
24
            else:
25
                print("INFO: Missing "+id.value+" in "+str(context.scene.objects.keys()))
26
                zuEntfernen.append(zaehler)
27
        # Überflüssige Schlüssel entfernen
28
        for schluessel in zuEntfernen:   
29
            model.markerIDs.remove(schluessel)
30
        return {'FINISHED'}
31
            
32
    # Platzhalter soll überschrieben werden
33
    def markerVerarbeiten(self,context,marker,model):
34
        #Texturen usw. packen
35
        bpy.ops.file.pack_all()
36
        print("pack_all")
37
        
38
class WechsleZuBART(WechsleBibliothek):
39
    """Aktiviert die Texturen von BART"""
40
    bl_idname = "texture.to_bart"
41
    bl_label  = "BART"
42
    
43
    # Aktiviert die Textur von BART
44
    def markerVerarbeiten(self,context,marker,model):
45
        #Texturen usw. packen
46
        bpy.ops.file.pack_all()
47
        
48
        #Erstelle Wörterbücher, die einem Marker die id des Texturschachtes mit der entsprechenden Textur zuordnen
49
        texturenBART = { marker.material_slots[0].material.texture_slots[i].texture.marker_id:i for i in range(0,18) if marker.material_slots[0].material.texture_slots[i] != None and marker.material_slots[0].material.texture_slots[i].texture.library == 'BART'}
50
        texturenALVAR = { marker.material_slots[0].material.texture_slots[i].texture.marker_id:i for i in range(0,18) if marker.material_slots[0].material.texture_slots[i] != None and marker.material_slots[0].material.texture_slots[i].texture.library == 'ALVAR'}
51
        
52
        for bild in range(context.scene.frame_start,context.scene.frame_end):
53
            bpy.context.scene.frame_set(bild)
54
            #Die passende Textur von BART aktivieren
55
            for schluessel in texturenBART:
56
                if((schluessel in texturenALVAR and marker.material_slots[0].material.use_textures[texturenALVAR[schluessel]]) or marker.material_slots[0].material.use_textures[texturenBART[schluessel]]):
57
                    print(bild,":",schluessel)
58
                    marker.material_slots[0].material.use_textures[texturenBART[schluessel]] = True
59
                    marker.material_slots[0].material.keyframe_insert("use_textures",index=texturenBART[schluessel],frame=bild,options={'INSERTKEY_NEEDED'})
60
            #Die Textur von ALVAR ggf. deaktivieren
61
            for index in texturenALVAR:
62
                marker.material_slots[0].material.use_textures[texturenALVAR[index]] = False
63
                marker.material_slots[0].material.keyframe_insert("use_textures",index=texturenALVAR[index],frame=bild,options={'INSERTKEY_NEEDED'})
64
        
65
class WechsleZuALVAR(WechsleBibliothek):
66
    """Aktiviert die Texturen von ALVAR"""
67
    bl_idname = "texture.to_alvar"
68
    bl_label  = "ALVAR"
69
    
70
    #  Aktiviert die Textur von ALVAR
71
    def markerVerarbeiten(self,context,marker,model):
72
        #Texturen usw. packen
73
        bpy.ops.file.pack_all()
74
        
75
        #Erstelle Wörterbücher, die einem Marker die id des Texturschachtes mit der entsprechenden Textur zuordnen
76
        texturenBART = { marker.material_slots[0].material.texture_slots[i].texture.marker_id:i for i in range(0,18) if marker.material_slots[0].material.texture_slots[i] != None and marker.material_slots[0].material.texture_slots[i].texture.library == 'BART'}
77
        texturenALVAR = { marker.material_slots[0].material.texture_slots[i].texture.marker_id:i for i in range(0,18) if marker.material_slots[0].material.texture_slots[i] != None and marker.material_slots[0].material.texture_slots[i].texture.library == 'ALVAR'}
78
        print("texturenBART",texturenBART)
79
        print("texturenALVAR",texturenALVAR)
80
        
81
        for bild in range(context.scene.frame_start,context.scene.frame_end):
82
            bpy.context.scene.frame_set(bild)
83

  
84
            #Die passende Textur von ALVAR aktivieren
85
            for schluessel in texturenALVAR:
86
                if((schluessel in texturenBART and marker.material_slots[0].material.use_textures[texturenBART[schluessel]]) or marker.material_slots[0].material.use_textures[texturenALVAR[schluessel]]):
87
                    marker.material_slots[0].material.use_textures[texturenALVAR[schluessel]] = True
88
                    marker.material_slots[0].material.keyframe_insert("use_textures",index=texturenALVAR[schluessel],frame=bild,options={'INSERTKEY_NEEDED'})
89
            
90
            #Die Textur von BART ggf. deaktivieren
91
            for index in texturenBART:
92
                marker.material_slots[0].material.use_textures[texturenBART[index]] = False
93
                marker.material_slots[0].material.keyframe_insert("use_textures",index=texturenBART[index],frame=bild,options={'INSERTKEY_NEEDED'})
plugin_blender/tools.py
1
import bpy
2

  
3
class Import1(bpy.types.Operator):
4
    """Fügt evtl. fehlende Schlüssel hinzu"""
5
    bl_idname = "tools.import1"
6
    bl_label  = "Import 1"
7
    
8
    # Wird ausgeführt um zu testen, ob die Operation des Operators möglich ist.
9
    @classmethod
10
    def poll(self, context):
11
        return True
12
    
13
    # Fügt evtl. fehlende Schlüssel hinzu
14
    def execute(self, context):
15
        #Ergänzt das Schlüsselattribut:
16
        for schluessel in bpy.data.objects.keys():
17
            if (schluessel[-2] == '_'):
18
                print(schluessel)
19
                bpy.data.objects[schluessel].marker_id = int(schluessel[-1])
20
            elif (schluessel[-3] == '_'):
21
                print(schluessel)
22
                bpy.data.objects[schluessel].marker_id = int(schluessel[-2:])
23
            elif (schluessel[-4] == '_'):
24
                print(schluessel)
25
                bpy.data.objects[schluessel].marker_id = int(schluessel[-3:])
26
        return{'FINISHED'}
27
            
28
class Import2(bpy.types.Operator):
29
    """Fügt neuere Schlüssel zu den Texturen hinzu"""
30
    bl_idname = "tools.import2"
31
    bl_label  = "Import 2"
32
    
33
    # Wird ausgeführt um zu testen, ob die Operation des Operators möglich ist.
34
    @classmethod
35
    def poll(self, context):
36
        return True
37
    
38
    # Fügt neuere Schlüssel zu den Texturen hinzu
39
    def execute(self, context):
40
        #Ergänzt die Schlüsselattribute:
41
        for schluessel in bpy.data.textures.keys():
42
            if(bpy.data.textures[schluessel].type == 'IMAGE'):
43
                if (schluessel[-2] == '_'):
44
                    print(schluessel)
45
                    bpy.data.textures[schluessel].marker_id = int(schluessel[-1])
46
                elif (schluessel[-3] == '_'):
47
                    print(schluessel)
48
                    bpy.data.textures[schluessel].marker_id = int(schluessel[-2:])
49
                elif (schluessel[-4] == '_'):
50
                    print(schluessel)
51
                    bpy.data.textures[schluessel].marker_id = int(schluessel[-3:])
52
              #      
53
                if(schluessel[0:5] == "ALVAR"):
54
                    print("Lib: ALVAR")
55
                    bpy.data.textures[schluessel].library = "ALVAR"
56
                elif(schluessel[0:4] == "BART"):
57
                    print("Lib: BART")
58
                    bpy.data.textures[schluessel].library = "BART"
59
        return{'FINISHED'}
plugin_blender/view.py
1
import bpy
2

  
3
class GraphischeOberflaeche(bpy.types.Panel):
4
    """Zeigt die graphische Oberfläche an"""
5
    bl_idname = "RENDER_PT_select"
6
    bl_label = "Teste für Markertracking"
7
    bl_space_type = 'PROPERTIES'
8
    bl_region_type = 'WINDOW'
9
    bl_context = "render"
10
    bl_options = {'DEFAULT_CLOSED'}
11

  
12

  
13
    @classmethod
14
    def poll(cls, context):
15
        return True
16
    
17
    def draw_header(self, context):
18
        pass
19
    
20
    def draw(self, context):
21
        #Eigenschaften der obersten Ebene
22
        layout = self.layout
23
        layout.prop(bpy.context.scene.markerRender,"kameraID",text="Kamera")
24
        layout.prop(bpy.context.scene.markerRender,"kameraDatenID",text="Kam.datenblock")
25
        #Kästen erzeugen 
26
        kasten1 = layout.box()
27
        kasten1.label("Erzeugung")
28
        kasten2 = layout.box()
29
        kasten2.label("Anpassung")
30
        kasten3 = layout.box()
31
        kasten3.label("Positionsdaten ausgeben")
32
        kasten4 = layout.box()
33
        kasten4.label("Texturen")
34
        # 1. Kasten füllen (Erzeugung)
35
        zeile1 = kasten1.row()
36
        zeile1.prop(bpy.context.scene.markerRender,"newMarkerID",text="nächste Nummer")
37
        zeile1.prop(bpy.context.scene.markerRender,"incrementNewMarkerID",text="autom. Erhöhen")
38
        zeile2 = kasten1.row()
39
        zeile2.prop(bpy.context.scene.markerRender,"kontrastErhoehen",text="hoher Kontrast")
40
        kasten1.operator("mesh.primitive_marker_add")
41
        # 2. Kasten füllen (Anpassung)
42
        kasten2.operator("scene.adjust_units",icon="SCENE_DATA")
43
        kasten2.operator("camera.adjust_camera",icon="CAMERA_DATA")
44
        kasten2.operator("render.adjust_dimensions",icon="RENDER_REGION")
45
        # 3. Kasten füllen (Positionsdaten ausgeben)
46
        k3_zeile1 = kasten3.row()
47
        k3_zeile1.prop(bpy.context.scene.markerRender,"markerID",text="Marker")
48
        k3_zeile2 = kasten3.row()
49
        k3_zeile2.prop(bpy.context.scene.markerRender,"dateipfad",text="")
50
        kasten3.operator("print_object.position",text="Ausgeben",icon="FILE_TEXT")
51
        # 4. Kasten füllen (Texturen)
52
        k4_zeile1 = kasten4.row()
53
        k4_zeile1.operator("texture.to_bart",icon="TEXTURE")
54
        k4_zeile1.operator("texture.to_alvar",icon="TEXTURE")

Also available in: Unified diff