@mfersaoui Yes it's safe.
Find an example below, that does what I described previously:
class BakeObject(c4d.plugins.ObjectData):
"""BakeObject Generator"""
def __init__(self, *args):
super(BakeObject, self).__init__(*args)
self.SetOptimizeCache(True)
def GetVirtualObjects(self, op, hierarchyhelp):
"""
This method is called automatically when Cinema 4D ask for the cache of an object. This is also the place
where objects have to be marked as input object by Touching them (destroy their cache in order to disable them in Viewport)
:param op: The Python Generator
:type op: c4d.BaseObject.
:param hh: The hierarchy helper.
:type hh: c4d.HierarchyHelp (currently a PyObject).
:return: The Representing object (c4d.LineObject or SplineObject)
"""
sphere = c4d.BaseObject(c4d.Osphere)
sphere[c4d.PRIM_SPHERE_SUB] = 48
sphere.MakeTag(c4d.Tphong)
return sphere
def Message(self, node, msgId, data):
"""
Called by Cinema 4D part to notify the object to a special event
:param node: The instance of the ObjectData.
:type node: c4d.BaseObject
:param msgId: The message ID type.
:type msgId: int
:param data: The message data.
:type data: Any, depends of the message passed.
:return: Depends of the message type, most of the time True.
"""
if msgId==c4d.MSG_DESCRIPTION_COMMAND:
if data['id'][0].id==1006:
if node.GetCache() is None:
return True
# Make sure no other thread are running
c4d.StopAllThreads()
# Retrieves a clone of the current object's cache.
cacheClone = node.GetCache().GetClone()
# Insert it into the current doc
node.GetDocument().InsertObject(cacheClone)
# Performs a Current State to Object to retrieve a polygonObject.
resultCSTO = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_CURRENTSTATETOOBJECT, list=[cacheClone], doc=node.GetDocument())
if not isinstance(resultCSTO, list) or not resultCSTO:
cacheClone.Remove()
raise RuntimeError("Failed to perform MCOMMAND_CURRENTSTATETOOBJECT.")
polygonizedCache = None
if resultCSTO[0].CheckType(c4d.Opolygon):
polygonizedCache = resultCSTO[0]
# If the results is a Null, performs a Join command to retrieve only one object.
elif resultCSTO[0].CheckType(c4d.Onull):
resultJoin = c4d.utils.SendModelingCommand(command=c4d.MCOMMAND_JOIN, list=[resultCSTO[0]], doc=node.GetDocument())
if not isinstance(resultJoin, list) or not resultJoin:
cacheClone.Remove()
for obj in resultCSTO:
obj.Remove()
raise RuntimeError("Failed to perform MCOMMAND_JOIN.")
polygonizedCache = resultJoin[0]
# Remove the cached clone of our Generator from the document since we get the poligonalized version of it
cacheClone.Remove()
if polygonizedCache is None:
return True
# Now that we have a PolygonObject we can perform our baking
# First we need a glossy material, so lets create it
glossyMat = c4d.Material()
# Disables teh color channel
glossyMat[c4d.MATERIAL_USE_COLOR] = False
# Removes the default specular layer
glossyMat.RemoveReflectionLayerIndex(0)
# Adds a layer
layer = glossyMat.AddReflectionLayer()
# Sets the Layer to GGX mode
glossyMat[layer.GetDataID() + c4d.REFLECTION_LAYER_MAIN_DISTRIBUTION] = c4d.REFLECTION_DISTRIBUTION_GGX
# Defines the Roughness float value
glossyMat[layer.GetDataID() + c4d.REFLECTION_LAYER_MAIN_VALUE_ROUGHNESS] = 0.0
# Defines the Reflection float value
glossyMat[layer.GetDataID() + c4d.REFLECTION_LAYER_MAIN_VALUE_REFLECTION] = 1.0
# Inserts glossy mat and the polygonized object into the document
node.GetDocument().InsertMaterial(glossyMat)
node.GetDocument().InsertObject(polygonizedCache)
# Assigns the glossy Mat to the Polygonized Object
textureTag = polygonizedCache.MakeTag(c4d.Ttexture)
textureTag[c4d.TEXTURETAG_MATERIAL] = glossyMat
# Now we can start the bake process
bakeData = c4d.BaseContainer()
bakeData[c4d.BAKE_TEX_WIDTH] = 512
bakeData[c4d.BAKE_TEX_HEIGHT] = 512
bakeData[c4d.BAKE_TEX_USE_PHONG_TAG] = True
bakeData[c4d.BAKE_TEX_CONTINUE_UV] = True
bakeData[c4d.BAKE_TEX_COLORPROFILE] = c4d.bitmaps.ColorProfile.GetDefaultLinearRGB()
bakeData[c4d.BAKE_TEX_FILL_COLOR] = c4d.Vector(0.0)
bakeData[c4d.BAKE_TEX_PIXELBORDER] = 12
bakeData[c4d.BAKE_TEX_REFLECTION] = True
bakeData[c4d.BAKE_TEX_UV_LEFT] = 0.0
bakeData[c4d.BAKE_TEX_UV_RIGHT] = 1.0
bakeData[c4d.BAKE_TEX_UV_TOP] = 0.0
bakeData[c4d.BAKE_TEX_UV_BOTTOM] = 1.0
# Initialize the Baking
bakeInfo = c4d.utils.InitBakeTexture(node.GetDocument(), textureTag, polygonizedCache.GetTag(c4d.Tuvw), polygonizedCache.GetTag(c4d.Tuvw), bakeData)
bakeDoc = bakeInfo[0]
bakeStatus = bakeInfo[1]
if bakeStatus != c4d.BAKE_TEX_ERR_NONE or bakeDoc is None:
polygonizedCache.Remove()
glossyMat.Remove()
return True
# Bake as a 32bit
bakeBmp = c4d.bitmaps.MultipassBitmap(512, 512, c4d.COLORMODE_RGBf)
bakeStatus = c4d.utils.BakeTexture(bakeDoc, bakeData, bakeBmp, c4d.threading.GeGetCurrentThread(), self.BakeTextureHook)
if bakeStatus != c4d.BAKE_TEX_ERR_NONE:
polygonizedCache.Remove()
glossyMat.Remove()
return True
# Dispay the baking result
c4d.bitmaps.ShowBitmap(bakeBmp)
# Cleanup temp stuff
polygonizedCache.Remove()
glossyMat.Remove()
return True
return True
def BakeTextureHook(self, info):
# Texture Baker hook, currently not used
# print info
pass
Cheers,
Maxime.