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()