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=550Code 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