Image2Vertex map



  • On 08/06/2015 at 16:39, xxxxxxxx wrote:

    Because i get so much help in the internet I want to share my plugin here.
    I used code fragments from here and there...
    It is a Bitmap to Vertexmap helper.
    The Script load a Bitmap from a texture tag. From color channel or alpha channel, or from a seperate file.
    Then it convert the bitmap to a vertexmap.

    Code is comment in german.

    Maybe someone helps:
    http://www.total3d.de/?page_id=550

    Code can surely be much better. (Like my english)
    But it works ;-)

      
    import c4d   
    import os   
    from c4d import bitmaps, storage   
    from c4d import utils,gui   
    from c4d.gui import GeDialog   
    from c4d.modules import render   
    import math   
      
      
    chlist = []   
    scaleart = 0   
    button = 0   
    alpha = 0   
    orig = bitmaps.BaseBitmap()   
    objekttext = ""   
    showo = False   
    shows = False   
    bitmapfile = ""   
      
      
    # Dialog erstellen   
    class Dialog(GeDialog) :   
        global objekttext, showo, shows   
        def __init__(self) :   
            pass   
           
        # Layout definieren   
        def CreateLayout(self) :   
            # Objektname in Beschreibungstext einfügen   
            objekttext = "Selected object is: "+op.GetName()   
            self.SetTitle("RenameTexture")    # Titel definieren   
              
            self.GroupBegin(1000,c4d.BFH_CENTER|c4d.BFH_SCALE|c4d.BFH_FIT,0,8)   
            self.AddStaticText(1001,c4d.BFH_CENTER|c4d.BFH_SCALE|c4d.BFH_FIT,800,10,"This is a simple image to vertex map converter!",0);   
            self.AddStaticText(1007,c4d.BFH_CENTER|c4d.BFH_SCALE|c4d.BFH_FIT,800,10,"Use at your own risk - Please save Document before use!",0);   
            self.AddSeparatorH(0,c4d.BFV_FIT)   
            self.AddStaticText(1009,c4d.BFH_CENTER|c4d.BFH_SCALE|c4d.BFH_FIT,800,10,"1) Please select an object.",0);   
            self.AddStaticText(1011,c4d.BFH_CENTER|c4d.BFH_SCALE|c4d.BFH_FIT,800,10,"2) Plugin use the first uvw tag of the select polygon object.",0);   
            self.AddStaticText(1012,c4d.BFH_CENTER|c4d.BFH_SCALE|c4d.BFH_FIT,800,10,"3) Please select a textur tag at the object.",0);   
            self.AddStaticText(1012,c4d.BFH_CENTER|c4d.BFH_SCALE|c4d.BFH_FIT,800,10,"4) Choose a button for use color map, alpha map or load a bitmap file.",0);   
            self.AddSeparatorH(0,c4d.BFV_FIT)   
            self.GroupEnd()   
      
            self.GroupBegin(1010,c4d.BFH_LEFT,1,1)   
            self.AddStaticText(1008,c4d.BFH_LEFT,800,10,objekttext,0);   
            self.AddSeparatorH(0,c4d.BFV_FIT)   
            self.GroupEnd()   
            self.GroupBegin(1010,c4d.BFH_LEFT,2,4)   
            self.AddCheckbox(1003,c4d.BFH_LEFT,10,10,"Bitmap COLOR Channel\n To Vertex Map!")   
            self.AddStaticText(1012,c4d.BFH_LEFT,800,10,"Show Bitmap in the picture manager",0);   
            self.AddCheckbox(1004,c4d.BFH_LEFT,10,10,"Bitmap COLOR Channel\n To Vertex Map!")   
            self.AddStaticText(1014,c4d.BFH_LEFT,800,10,"Show scaled bitmap in picture manager",0);   
            self.GroupEnd()   
      
            self.GroupBegin(1000,c4d.BFH_LEFT|c4d.BFH_SCALE|c4d.BFH_FIT,1,3)   
            self.AddStaticText(1001,c4d.BFH_LEFT,800,10,"How much scale the bitmap before check color :",0);   
            self.AddEditSlider(1002,c4d.BFH_LEFT|c4d.BFH_SCALE|c4d.BFH_FIT, 10, 0)         
            self.GroupEnd()   
      
            self.AddSeparatorV(0,c4d.BFV_FIT)   
              
            self.GroupBegin(1020,c4d.BFV_CENTER,3,1)   
            self.AddButton(1022,c4d.BFH_CENTER,0,40,"Bitmap COLOR Channel\n To Vertex Map!")   
            self.AddButton(1023,c4d.BFH_CENTER,0,40,"Bitmap ALPHA Channel\n To Vertex Map!")   
            self.AddButton(1024,c4d.BFH_CENTER,0,40,"Load a Bitmap File\n To Vertex Map!")   
            self.GroupEnd()   
            return True   
      
           
        # Dialog Verarbeitung definieren   
        def Command(self,id,msg) :   
            global chlist, scaleart, orig, alpha, button, showo, shows, bitmapfile   
              
            button = id    # Variable button für Benutzung im Hauptprogramm speichern   
            if(id < 1002 or id > 1005) :# Wurde nur der Slider, oder die Checkboxen verändert? Dann mit True zurückgeben   
                if(id == 1022 or id == 1023) : # Button links oder mitte (Color oder Alpha) wurde gedrückt   
                   # Button 1 (Alpha Channel) gedrückt   
                   if (id == 1023) : alpha = 1                 
                   #Scalierungs Slider speichern   
                   scaleart = int (self.GetReal(1002) * 0.1)       
                   showo= self.GetBool(1003)          
                   shows= self.GetBool(1004)          
                   self.Close()    # Fenster schließen und weiter im Hauptprogramm   
                   return True   
                else:   
                   if (id == 1024) :# Der Button rechts für die Datei-Auswahl wurde gedrückt   
                        # Datei-Dialog öffnen   
                        bitmapfile = c4d.storage.LoadDialog (type=c4d.FILESELECTTYPE_IMAGES, title="Select a bitmap file for mapping!", flags=c4d.FILESELECT_LOAD)   
                        if not bitmapfile:   
                            gui.MessageDialog("no File loading!")   
                            return False   
                        scaleart = int (self.GetReal(1002) * 0.1)       
                        showo= self.GetBool(1003)          
                        shows= self.GetBool(1004)      
                        self.Close()   
                        return True   
                   else:   
                        self.Close()   
                        return False   
            return True   
      
      
      
      
    def main() :   
        # globale Variablen übernehmen   
        global scaleart, orig, alpha, button, showo, shows, bitmapfile   
      
        c4d.CallCommand (13957) # Pythonkonsole leeren   
           
        # Objekt ausgewählt? Sonst Fehlerausgabe und beenden   
        if not op:   
            gui.MessageDialog("Please select a object!")   
            return False                        # EXIT   
           
        # Prüfen ob das Objekt ein Polygonobjekt ist   
        if (op.GetType()== 5100) :           # 5100 ist der Type für das Polygonobjekt   
            print   
        else:   
            gui.MessageDialog("ERROR - Object is not a polygon object?")   
            return False   
              
        # Erstes UVTag auslesen   
        uvtag = op.GetTag(c4d.Tuvw)   
        # Kein UVW Tag? Sonst Fehlerausgabe und beenden   
        if not uvtag:   
            gui.MessageDialog("Please assign UVW to the object")   
            return   
           
        # Dialog aufrufen   
        dlg = Dialog();   
        dlg.Open(c4d.DLG_TYPE_MODAL)   
        if (button == 0) : return False    # Kein Button gedrückt (z.B. beim Fenster schließen über Fensterelement X)   
           
        # Bitmap Variablen vorbereiten   
        smallbitm = bitmaps.BaseBitmap()   
        bitmap = bitmaps.BaseBitmap()          
        bitmapPath = bitmapfile   
      
        if (button == 1024) :   
            abspath = bitmapfile   
            bitmapPath = bitmapfile   
        else:   
            # Selektiertes Tag auslesen   
            ttag = doc.GetActiveTag()   
            if (not ttag or not ttag.CheckType(c4d.Ttexture) ) : # Falls kein Material Tag vorhanden oder/und ausgewählt - abbrechen   
                gui.MessageDialog("Please attach AND SELECT a Material to the object!")   
                return False   
      
            # Material der Variable mat zuweisen   
            mat = ttag.GetMaterial()   
           
            # Kein Material übernehmen können? Dann Fehlerausgabe und beenden   
            if not mat:   
                gui.MessageDialog("Please attach a Material with simple bitmap in color Channel to the object!")   
                return False # EXIT   
      
            # Farbkanal auslesen falls Variable alpha = 0 (Button links gedrückt)   
            if (alpha == 0) :   
                if (mat[c4d.MATERIAL_USE_COLOR] == True) : # ist der Color kanal des Materials aktiv?   
                   shader = mat[c4d.MATERIAL_COLOR_SHADER] # dann Shader auslesen   
                else:   
                   gui.MessageDialog("Miss COLOR Channel!")   
                   return False # Exit   
            # Alphakanal auslesen falls Variable alpha = 1 (Button mitte gedrückt)   
            if (alpha == 1) :   
                if (mat[c4d.MATERIAL_USE_ALPHA] == True) : # ist der Alpha kanal des Materials aktiv?   
                   shader = mat[c4d.MATERIAL_ALPHA_SHADER] # dann Shader auslesen   
                else:   
                   gui.MessageDialog("Miss ALPHA Channel!")   
                   return False # Exit   
              
            # Farbkanal / Alphakanal konnte nicht gelesen werden?   
            if shader is None:   
                if (alpha == 0) : gui.MessageDialog("Can't get the Shader!\nPlease check that the COLOR Channel is not empty!")   
                if (alpha == 1) : gui.MessageDialog("Can't get the Shader!\nPlease check that the ALPHA Channel is not empty!")   
                return False # EXIT   
              
              
            # Shader vor dem auslesen erst abrufbar machen!!!   
            bitmapPath = shader[c4d.BITMAPSHADER_FILENAME]   
            # Shadertyp und Filename bei Bitmapshader auslesen   
            name, path = shader.GetName(), shader[c4d.BITMAPSHADER_FILENAME]   
                   
            #if bitmapPath is´nt absolute   
            if not os.path.dirname(bitmapPath) :   
                #the document has´nt been saved already ->picture in user library   
                if not doc.GetDocumentPath() :   
                   abspath= c4d.storage.GeGetStartupWritePath()+"/"+"tex"+"/"+bitmapPath   
                #the picture should be inside the asset´s texture folder       
                else:   
                   abspath= doc.GetDocumentPath()+"/"+bitmapPath   
            else:   
                abspath = bitmapPath   
      
           
           
        #   
        if op is not None:       
              
            # Bitmap mit vollem Pfad und Dateinamen Initialisieren:   
            result = bitmap.InitWith(abspath)   
      
            if (button <> 1024) : irs = render.InitRenderStruct()   
            else: irs = True   
            if (button <> 1024) : shader.InitRender(irs)   
            if irs:   
      
                   
                # Bitmapdateien in Shadern können absolut oder relativ gespeichert werden.   
                # Also muss geprüft werden ob der komplette Pfad ausgelesen wurde!   
      
      
                # Falls Bitmap ordnungsgemäß verarbeitet wurde:   
                if result:   
                     
                   # Die Variable bitmap wurde jetzt auf eine von 3 Arten befüllt:   
                   if bitmap is not None: # hats geklappt? Dann weiter:   
                        width, height = bitmap.GetSize()       # Pixel-Maße der Bilddatei auslesen   
                        bits = bitmap.GetBt()                  # Bittiefe auslesen   
                        pixelzahl = width*height               # Gesamtpixelanzahl ermitteln   
                        punktezahl = uvtag.GetDataCount()      # Punkteanzahl der UVW-Map ermitteln   
      
      
                        # Scalierung auf basis des Skalierungs-Sliders berechnen   
                        # Aufgrund der Differenz der Auflösung der Bilddatei   
                        # und der Auflösung des Polygonmesh (bzw. der UVW-Map)   
                        # berechnet sich die Scalierung der Bilddatei.   
                        # Die Bilddatei wird skaliert damit in einer hohen Bildauflösung   
                        # ein einzelner ausgerissener Pixel den Punkt in einem niedrig aufgelösen Mesh                        # nicht so stark beeinflusst beeinflusst. nur weil der UV-Punkt genau auf diesem Pixel liegt.   
                           
                        differenz = pixelzahl - punktezahl             # Differenz ermitteln   
                        if scaleart == 10: diffadd = float(differenz)/1000    # Neue Bildgröße = Anzahl der Punkte der UV-Map + Differenz geteilt durch 1000   
                        if scaleart == 9: diffadd = float(differenz)/500     # Neue Bildgröße = Anzahl der Punkte der UV-Map + Differenz geteilt durch 500   
                        if scaleart == 8: diffadd = float(differenz)/100      # Neue Bildgröße = Anzahl der Punkte der UV-Map + Differenz geteilt durch 100   
                        if scaleart == 7: diffadd = float(differenz)/50       # Neue Bildgröße = Anzahl der Punkte der UV-Map + Differenz geteilt durch 50                           
                        if scaleart == 6: diffadd = float(differenz)/20       # Neue Bildgröße = Anzahl der Punkte der UV-Map + Differenz geteilt durch 20   
                        if scaleart == 5: diffadd = float(differenz)/10       # Neue Bildgröße = Anzahl der Punkte der UV-Map + Differenz geteilt durh 10   
                        if scaleart == 4: diffadd = float(differenz)/5        # Neue Bildgröße = Anzahl der Punkte der UV-Map + Differenz geteilt durch 5   
                        if scaleart == 3: diffadd = float(differenz)/3        # Neue Bildgröße = Anzahl der Punkte der UV-Map + ein Drittel der Differenz   
                        if scaleart == 1: diffadd = float(differenz)/2        # Neue Bildgröße = Anzahl der Punkte der UV-Map + die Hälfte der Differenz   
                        if scaleart == 2: diffadd = float((differenz/3))*2    # Neue Bildgröße = Anzahl der Punkte der UV-Map + Zwei Drittel der Differenz   
                        if scaleart == 0: diffadd = differenz          # Neue Bildgröße = Anzahl der Punkte der UV-Map + komplette Defferenz - Also volle Auflösung!   
      
                        # Geladenes Bild bestimmt das Seitenverhältnis. Anhand der alten Menge an Pixel,   
                        # der zur Verfügung stehenden Punkte im UV-Mesh und dem Grad der Skalierung (Slider)   
                        # wird die neue Bildgröße berechnet. mit gleich bleibenden Seitenverhältnis.   
      
                        # Scalierungsfaktor berechnen: Punkte+Pixelreduzierung geteilt durch Pixelanzahl   
                        scalefaktor = float(punktezahl+diffadd) / (pixelzahl)   
                        # Anhand des Skalierungsfaktors der Fläche die Seitenlängen berechnen                           
                        scale_width = int(width * math.sqrt(scalefaktor))              
                        scale_height = int(height * math.sqrt(scalefaktor))   
                                                      
      
                        # Kleinere Version der Bitmap erstellen   
                        smallbitm.Init(scale_width, scale_height, bits)    # Kleinere Maße, gleiche Bittiefe, gleiches Seitenverhältnis   
      
                        # Copy&Scale; Original Bitmap zu Kleine Bitmap   
                        bitmap.ScaleBicubic(smallbitm, 0, 0, width-1, height-1, 0, 0, scale_width-1, scale_height-1)   
                           
                        if (showo == True) : bitmaps.ShowBitmap(bitmap)   
                        if (shows == True) : bitmaps.ShowBitmap(smallbitm)   
                        bitmap = smallbitm   
      
                   else:   
                        gui.MessageDialog("Bitmap-Error")   
                        return False   
      
                   if (button <> 1024) : shader.FreeRender()   
                     
                   # Abbrechen falls Bitmap nicht übergeben werden konnte   
                   if bitmap is None:   
                        gui.MessageDialog("Bitmap can't load")   
                        return False   
                               
                else:   
                   # Im Kanal steckt keine einfache Bitmap-Datei. Wahrscheinlich ein prozeduraler Shader, oder Ebenen ect.   
                   gui.MessageDialog("In channel ist not a simple bitmap")   
                   return False                           # EXIT   
                     
                # Es wird eine Vertexmap erstellt die gleichviele Punkte enthält wie das Polygonobjekt   
                vtag = c4d.VariableTag(c4d.Tvertexmap, op.GetPointCount())   
                bitmap_w = bitmap.GetBw()              # Breite der Bitmap auslesen   
                bitmap_h = bitmap.GetBh()              # Höhe der Bitmap auslesen   
                pixel = (bitmap_w * bitmap_h)          # Pixelanzahl des Skalierten Bildes   
                points = uvtag.GetDataCount()          # Punktanzahl des UVW-Tags   
                if (op.GetPointCount() > 0) :           # Prüfen ob das Objekte Punkte zum auslesen hat   
                   vertexList = op.GetPointCount() * [0] # Die Variable für die Vertagsmap-Befüllung mit der Anzahl an Punkten des selektierten Objektesvorbereiten   
                else:   
                   gui.MessageDialog("Object have no read able points! Is it a polygon object?")   
                   return False   
                   
                # Schleife liest jedes UVW-tag Polygon aus. Ein Punkt eines UVW-Tags kann mehreren Polygonobjekt-Punkten zugewisen sein   
                # Es wird der Reihe nach jedes UV-Polygon ausgelesen. Dann wird das zugehörige Polygon des Objektes ausgelesen und   
                # dessen Punkte mit den Farbwerten der Bitmap gefüllt. Die Anzahl der Polygonpunkte müssen nämlich gleich sein mit der Anzahl der Vertexmap-Punkte   
                   
                # Laut Wiki: Grauwert = 0,299 × Rotanteil + 0,587 × Grünanteil + 0,114 × Blauanteil   
                   
                for i in xrange(uvtag.GetDataCount()) : # Schleife durchläuft Polygone des UVW-Tag   
                        uvwdict = uvtag.GetSlow(i)     # UVW-Polygon wird eingelesen   
                        objpolygon = op.GetPolygon(i) # Objekt-Polygon wird eingelesen   
                        point_a = op.GetPoint(objpolygon.a) # Objekt Polygon-PunktA ID wird ausgelesen   
                        point_b = op.GetPoint(objpolygon.b) # Objekt Polygon-PunktB ID wird ausgelesen   
                        point_c = op.GetPoint(objpolygon.c) # Objekt Polygon-PunktC ID wird ausgelesen   
                        point_d = op.GetPoint(objpolygon.d) # Objekt Polygon-PunktD ID wird ausgelesen   
                        u = uvwdict["a"].x                  # UVW-Koordinate des Punktes A wird ermittelt   
                        v = uvwdict["a"].y                  # UVW-Koordinate des Punktes A wird ermittelt   
                        w = uvwdict["a"].z   
                        ux = bitmap_w*u                     # UV-Koordinate liegt zwischen 0-1 und wird mit der Bildbreite multipliziert   
                        uy = bitmap_h*v                     # UV-Koordinate liegt zwischen 0-1 und wird mit der Bildhöhe multipliziert   
                        color = bitmap.GetPixel(int(ux), int(uy))   
                        # "ubjektiver" Helligkeitswert aus RGB ermitteln   
                        weight_a = 0.299 * (float(color[0])/256) + 0.587 * (float(color[1])/256) + 0.114 * (float(color[2])/256)   
      
                        u = uvwdict["b"].x                  # UVW-Koordinate des Punktes B wird ermittelt   
                        v = uvwdict["b"].y                  # UVW-Koordinate des Punktes B wird ermittelt   
                        w = uvwdict["b"].z   
                        ux = bitmap_w*u                     # UV-Koordinate liegt zwischen 0-1 und wird mit der Bildbreite multipliziert   
                        uy = bitmap_h*v                     # UV-Koordinate liegt zwischen 0-1 und wird mit der Bildhöhe multipliziert   
                        color = bitmap.GetPixel(int(ux), int(uy))   
                        # "ubjektiver" Helligkeitswert aus RGB ermitteln   
                        weight_b = 0.299 * (float(color[0])/256) + 0.587 * (float(color[1])/256) + 0.114 * (float(color[2])/256)   
      
                        u = uvwdict["c"].x                  # UVW-Koordinate des Punktes C wird ermittelt   
                        v = uvwdict["c"].y                  # UVW-Koordinate des Punktes C wird ermittelt   
                        w = uvwdict["c"].z   
                        ux = bitmap_w*u                     # UV-Koordinate liegt zwischen 0-1 und wird mit der Bildbreite multipliziert   
                        uy = bitmap_h*v                     # UV-Koordinate liegt zwischen 0-1 und wird mit der Bildhöhe multipliziert   
                        color = bitmap.GetPixel(int(ux), int(uy))   
                        # "ubjektiver" Helligkeitswert aus RGB ermitteln   
                        weight_c = 0.299 * (float(color[0])/256) + 0.587 * (float(color[1])/256) + 0.114 * (float(color[2])/256)   
      
                        u = uvwdict["d"].x                  # UVW-Koordinate des Punktes D wird ermittelt   
                        v = uvwdict["d"].y                  # UVW-Koordinate des Punktes D wird ermittelt   
                        w = uvwdict["d"].z   
                        ux = bitmap_w*u                     # UV-Koordinate liegt zwischen 0-1 und wird mit der Bildbreite multipliziert   
                        uy = bitmap_h*v                     # UV-Koordinate liegt zwischen 0-1 und wird mit der Bildhöhe multipliziert   
                        color = bitmap.GetPixel(int(ux), int(uy))   
                        # "ubjektiver" Helligkeitswert aus RGB ermitteln   
                        weight_d = 0.299 * (float(color[0])/256) + 0.587 * (float(color[1])/256) + 0.114 * (float(color[2])/256)   
      
                        # Helligkeitswerte der Vertexmap Wert-Variable zuweisen   
                        vertexList[objpolygon.a] = weight_a   
                        vertexList[objpolygon.b] = weight_b   
                        vertexList[objpolygon.c] = weight_c   
                        vertexList[objpolygon.d] = weight_d   
                               
                if vtag: # falls die Vertexmap auch wirlich erstellt wurde kann es weiter gehen:   
                   op.InsertTag(vtag) # Vertexmap wird an dem objekt erstellt   
      
                   vtag.SetAllHighlevelData(vertexList) # erstellte Vertexmap wird mit den ermittelten Werten gefüllt   
                               
                c4d.EventAdd() # Veränderung in der Szene mitteilen, damit C4D aktualisiert.   
            else:   
                # Das Vorbereiten der Bitmapinitialisierung hat fehlgeschlagen:   
                gui.MessageDialog("Can Not Init Shader")   
                if irs == c4d.INITRENDERRESULT_OUTOFMEMORY: gui.MessageDialog("Out Of Memory")   
                if irs == c4d.INITRENDERRESULT_ASSETMISSING: gui.MessageDialog("Texture Not Assigned")   
                if irs == c4d.INITRENDERRESULT_UNKNOWNERROR: gui.MessageDialog("Unknown Error")   
                if irs == c4d.INITRENDERRESULT_THREADEDLOCK: gui.MessageDialog("Threaded Lock")   
              
            gui.MessageDialog(" - Finish - ")   
      
    if __name__=='__main__':   
        main()   
      
    


  • On 09/06/2015 at 01:09, xxxxxxxx wrote:

    Hi,

    thanks for sharing!
    As I wrote a similar plugin, last year, for an in house production I want to ask if you feel like working together and publish an optimized version with a few more features?
    If so, feel free to send me a pm.

    Best wishes
    Martin



  • On 09/06/2015 at 08:11, xxxxxxxx wrote:

    Hello,

    thank you for sharing your work!

    Best wishes,
    Sebastian


Log in to reply