On 08/06/2013 at 16:27, xxxxxxxx wrote:
Originally posted by xxxxxxxx
Thanks Tom.
But I figured it out. And got it working.
Originally posted by xxxxxxxx
This has to in the .res file for the gradient gizmo to show up: INCLUDE xsdkgradient;
Sorry, but I think there you are mistaken.
Okay I indeed used the xsdkgradient.h, xsdkgradient.res and xsdkgradient.str from the original C++ SDK gradient example, but very well-considered and only to stay as close as possible to that certain example.
So that it will be as comparable as it gets in the end.
But it is absolutely not required for that task.
You could also build up the whole resources stuff by yourself.
It really sounds to me like the symbol cache problem I mentioned above!
So please do me a favor, search for the "symbolcache" file in the C4D "{USER_FOLDER}/prefs/", delete it and then try your old method without the extra include again.
At least try it and then tell me about it, okay? :wink:
(Of course there could also be another problem, but I'm quite sure that's it in your case, really!)
Originally posted by xxxxxxxx
I looked at your code.
You did a good job converting it to Python.
Oh, thank you very much! :blush:
Originally posted by xxxxxxxx
But the problem you're having with the turbulence looks like a conversion problem from C++ Python.
I guess you can't use commas with multiple variables the same way in Python as it's written in C++.
Hey, great find! You're absolutely right. :clap:
As a matter of fact I hadn't checked and compared the parameter list of this function implementation in both coding languages but merely changed the syntax to Python.
That was a bit careless from me and indeed there is a little difference. :joy:
That's the original C++ code line:
res = Vector(Turbulence(p*scl,tt,gdata.octaves,TRUE),Turbulence((p+Vector(0.34,13.0,2.43))*scl,tt,gdata.octaves,TRUE),0.0);
And so it have to look like in Python:
res = c4d.Vector(Turbulence(p * scl, self.octaves, True, tt), Turbulence((p+c4d.Vector(0.34, 13.0, 2.43)) * scl, self.octaves, True, tt), 0.0)
Or to make it short: the time parameter of the C4DNoise.Turbulence() function simply has to jump from the middle of the list to the end. ;)
But of course that wasn't the reason for the main problem.
The real trouble came from the one line that I temporarily commented out and dismissed overhasty as "just" a safety check.
So yes, the code is complete now and works, as it should. :slightly_smiling_face:
Unfortunately I have to admit, that I still couldn't figure out what exactly this line is for and why it's so essential?
Obviously the important element here have to be the "gradient.InitRender(irs)" because the gradient itself should normally always be true.
But as I said, it's so far complete now and should be working as expected (or at least I hope so :wink:) and so here it is again: :slightly_smiling_face:
#############################################################
## CINEMA 4D Python Gradient Shader ##
## [1:1 conversion from the analogical C++ SDK example] ##
## [originally done by the MAXON Computer GmbH] ##
#############################################################
## (c) 2013 Thomas Chen, all rights reserved ##
#############################################################
## Python-Gradient.pyp ##
#############################################################
import os
import math
import c4d
from c4d import plugins, bitmaps, utils, storage, gui
from c4d.utils.noise import Turbulence
#warning Please obtain your own plugin ID from http://www.plugincafe.com
PLUGIN_ID = 1000001
class SDKGradientClass(plugins.ShaderData) :
cycle = False
mode = 0
angle = 0.0
c = [0.0, 0.0, 0.0, 0.0] # maybe not optimal?
sa = 0.0
ca = 0.0
turbulence = 0.0
octaves = 5.0
scale = 1.0
freq = 1.0
absolute = False
gradient = c4d.Gradient()
def Init(self, node) :
#Called when a new instance of the node plugin has been allocated.
k1_col = c4d.Vector(0.0, 0.0, 1.0)
k1_pos = 0.0
k2_col = c4d.Vector(1.0, 1.0, 1.0)
k2_pos = 1.0
self.gradient.InsertKnot(col = k1_col, pos = k1_pos)
self.gradient.InsertKnot(col = k2_col, pos = k2_pos)
node[c4d.SDKGRADIENTSHADER_COLOR] = self.gradient
node[c4d.SDKGRADIENTSHADER_CYCLE] = self.cycle
node[c4d.SDKGRADIENTSHADER_MODE] = self.mode
node[c4d.SDKGRADIENTSHADER_ANGLE] = self.angle
node[c4d.SDKGRADIENTSHADER_TURBULENCE] = self.turbulence
node[c4d.SDKGRADIENTSHADER_OCTAVES] = self.octaves
node[c4d.SDKGRADIENTSHADER_SCALE] = self.scale
node[c4d.SDKGRADIENTSHADER_FREQ] = self.freq
node[c4d.SDKGRADIENTSHADER_ABSOLUTE] = self.absolute
return True
def InitRender(self, sh, irs) :
#Precalculate any data for rendering.
self.mode = sh[c4d.SDKGRADIENTSHADER_MODE]
self.angle = sh[c4d.SDKGRADIENTSHADER_ANGLE]
self.cycle = sh[c4d.SDKGRADIENTSHADER_CYCLE]
self.turbulence = sh[c4d.SDKGRADIENTSHADER_TURBULENCE]
self.octaves = sh[c4d.SDKGRADIENTSHADER_OCTAVES]
self.scale = sh[c4d.SDKGRADIENTSHADER_SCALE]
self.freq = sh[c4d.SDKGRADIENTSHADER_FREQ]
self.absolute = sh[c4d.SDKGRADIENTSHADER_ABSOLUTE]
self.gradient = sh[c4d.SDKGRADIENTSHADER_COLOR]
if (not self.gradient) or (not self.gradient.InitRender(irs)) : return c4d.INITRENDERRESULT_OUTOFMEMORY
self.sa, self.ca = utils.SinCos(self.angle)
for i in range (0, 4) :
self.c[i] = 0.0
k = self.gradient.GetKnot(i) # here I had to use "Gradient.GetKnot(index)" because there is no "Gradient.GetRenderKnot(index)" in the Python SDK.
if (k) : self.c[i] = k['col']
return 0
def FreeRender(self, sh) :
#Free any resources used for the precalculated data from InitRender()
if (self.gradient) : self.gradient.FreeRender()
self.gradient = None
def Output(self, sh, cd) :
#Called for each point of the visible surface of a shaded object. Here you should calculate and return the channel color for the point cd.p.
p = cd.p
r = 0.0
if (self.turbulence > 0.0) :
scl = 5.0 * self.scale
tt = cd.t * self.freq * 0.3
res = c4d.Vector(Turbulence(p * scl, self.octaves, True, tt), Turbulence((p+c4d.Vector(0.34, 13.0, 2.43)) * scl, self.octaves, True, tt), 0.0)
if self.absolute:
p.x = utils.MixNum(p.x, res.x, self.turbulence)
p.y = utils.MixNum(p.y, res.y, self.turbulence)
else:
p.x += (res.x - 0.5) * self.turbulence
p.y += (res.y - 0.5) * self.turbulence
#rotation
p.x -= 0.5
p.y -= 0.5
xx = self.ca * p.x - self.sa * p.y + 0.5
yy = self.sa * p.x + self.ca * p.y + 0.5
p.x = xx
p.y = yy
if (self.mode <= c4d.SDKGRADIENTSHADER_MODE_CORNER) and self.cycle and (cd.texflag & c4d.TEX_TILE) :
if cd.texflag is c4d.TEX_MIRROR:
p.x = p.x % 2.0
if p.x >= 1.0: p.x = 2.0 - p.x
p.y = p.y % 2.0
if p.y >= 1.0: p.y = 2.0 - p.y
else:
p.x = p.x % 1.0
p.y = p.y % 1.0
if self.mode is c4d.SDKGRADIENTSHADER_MODE_U:
r = p.x
elif self.mode is c4d.SDKGRADIENTSHADER_MODE_V:
r = 1.0 - p.y
elif self.mode is c4d.SDKGRADIENTSHADER_MODE_DIAGONAL:
r = (p.x + p.y) * 0.5
elif self.mode is c4d.SDKGRADIENTSHADER_MODE_RADIAL:
p.x -= 0.5
p.y -= 0.5
if p.x == 0.0: p.x = 0.00001
angle = math.atan(p.y / p.x)
if p.x < 0.0: angle += math.pi
if angle < 0.0: angle += (math.pi * 2.0)
r = angle / (math.pi * 2.0)
elif self.mode is c4d.SDKGRADIENTSHADER_MODE_CIRCULAR:
p.x -= 0.5
p.y -= 0.5
r = math.sqrt(p.x * p.x + p.y * p.y) * 2.0
elif self.mode is c4d.SDKGRADIENTSHADER_MODE_BOX:
p.x = abs(p.x - 0.5)
p.y = abs(p.y - 0.5)
r = max(p.x, p.y) * 2.0
elif self.mode is c4d.SDKGRADIENTSHADER_MODE_STAR:
p.x = abs(p.x - 0.5) - 0.5
p.y = abs(p.y - 0.5) - 0.5
r = math.sqrt(p.x * p.x + p.y * p.y) * 1.4142
elif self.mode is c4d.SDKGRADIENTSHADER_MODE_CORNER:
cx = utils.FCut(p.x, 0.0, 1.0)
ca = utils.MixVec(self.c[0], self.c[1], cx)
cb = utils.MixVec(self.c[2], self.c[3], cx)
return utils.MixVec(ca, cb, utils.FCut(p.y, 0.0, 1.0))
return self.gradient.CalcGradientPixel(utils.FCut(r, 0.0, 1.0))
def RegisterSDKGradientClass() :
fn = os.path.join(os.path.dirname(__file__), "res", "gradienttypes.tif")
bmp = bitmaps.BaseBitmap()
if c4d.IMAGERESULT_OK != bmp.InitWith(fn)[0]: return False
gui.RegisterIcon(200000135, bmp, 0*32, 0, 32, 32)
gui.RegisterIcon(200000136, bmp, 1*32, 0, 32, 32)
gui.RegisterIcon(200000137, bmp, 2*32, 0, 32, 32)
gui.RegisterIcon(200000138, bmp, 3*32, 0, 32, 32)
gui.RegisterIcon(200000139, bmp, 4*32, 0, 32, 32)
gui.RegisterIcon(200000140, bmp, 5*32, 0, 32, 32)
gui.RegisterIcon(200000141, bmp, 6*32, 0, 32, 32)
gui.RegisterIcon(200000142, bmp, 7*32, 0, 32, 32)
return plugins.RegisterShaderPlugin(PLUGIN_ID, "Python Gradient", 0, SDKGradientClass, "xsdkgradient", 0)
if __name__ == '__main__':
RegisterSDKGradientClass()
Kind regards,
Tom