Modifiying the normal-tag
-
On 17/03/2014 at 17:29, xxxxxxxx wrote:
I'm having some trouble using your custom set_normals() method.
It's throwing a type error.
Any idea why? Am I using it wrong?import c4d def float2bytes(f) : int_value = int(math.fabs(f * 32000.0)) high_byte = int(int_value / 256) low_byte = int_value - 256 * high_byte if f < 0: high_byte = 255-high_byte low_byte = 255-low_byte return (low_byte,high_byte) def set_normals(normal_tag,polygon,normal_a,normal_b,normal_c,normal_d) : normal_list = [normal_a,normal_b,normal_c,normal_d] normal_buffer = normal_tag.GetLowlevelDataAddressW() vector_size = 6 component_size = 2 for v in range(0,4) : normal = normal_list[v] for c in range(0,3) : low_byte, high_byte = float2bytes(normal[c]) #<--- TypeError: int is unscriptable normal_buffer[normal_tag.GetDataSize()*polygon+v*vector_size+c*component_size+0] = chr(low_byte) normal_buffer[normal_tag.GetDataSize()*polygon+v*vector_size+c*component_size+1] = chr(high_byte) def main() : obj = doc.GetActiveObject() normalTag = obj.GetFirstTag() #Assuming the normal tag is the first tag polys = obj.GetAllPolygons() #Change the normals for the first polygon in the normal tag set_normals(normalTag, polys[0], polys[0].a, polys[0].b, polys[0].c, polys[0].d) if __name__=='__main__': main()
-ScottA
-
On 18/03/2014 at 01:57, xxxxxxxx wrote:
Just to add something here, the function "SetAllHighlevelData()" works and you can set normals, just only some of them.
Let's say we have only polygon, according to the documentation there should be 12 integers to set (for each of the 4 vectors 3 values (x,y,z)). Reading the normals using the "GetAllHighlevelData()" function you get an integer array with the length of 12 as expected. Trying to set the normals using this array throws the error I mentioned before. When you only set an array with the length of 1 the function works (but isn't useful at all, because you can only set the x-value of the first vector).
If you have 2 polygons, you are able to set an array with the length of 2, 3 polygons -> array with the length of 3, and so on. Maybe there is a trick to this, I don't know. But in fact you can set normals using this mehtod, only not the way you'd expect.
Also a funny thing: "GetAllHighlevelData()" seems to scramble the order of the normals if you have more than one polygon. I don't think this is intended. Anyway it's easier to get just the normals using the "CreatePhongNormals()"-function.
I'll give reverend's approach a try as soon as I have time.
Phil -
On 18/03/2014 at 02:16, xxxxxxxx wrote:
sorry, I did not explain how to call my functions...
and thanks hgcafe for pointing out what works with the highlevel functions.
I made the implementation similar to the uvwtag.SetSlow() function (for the parameters to use), so setting the normals for points a,b,c,d of polygon 0 to the "up" vector (0,1,0) would be:normal_a = c4d.Vector(0.0,1.0,0.0) normal_b = c4d.Vector(0.0,1.0,0.0) normal_c = c4d.Vector(0.0,1.0,0.0) normal_d = c4d.Vector(0.0,1.0,0.0) set_normals(normal_tag,0,normal_a,normal_b,normal_c,normal_d)
so set_normals expects a normal tag as 1st parameter, a polygon index number (int) as the 2nd parameter and the 4 normalized normal vectors.
Unfortunately there is no SetSlow() for a normal tag... -
On 18/03/2014 at 08:40, xxxxxxxx wrote:
Hmm. Nope.
That just changes the error to this: TypeError: 'c4d.Vector' object is unsubscriptable-ScottA
-
On 18/03/2014 at 10:35, xxxxxxxx wrote:
hmm, which version of Cinema4D do you use?
iterating over Vector components was introduced in R14.014.
see the current Python SDK.Vector.__getitem__(self, key) New in version R14.014. Gets X, Y and Z components by index. Note: The Vector objects does not support item deletion. For instance by calling del(v[0]). Parameters: key (int) – The component index. value (float) – The new vector component. Raises IndexError: If the index key is out of range : 0<=key<2.
if you have a previous version you might to have to change the code...
-
On 18/03/2014 at 10:42, xxxxxxxx wrote:
maybe its another problem...
in your code you wrote:polys = obj.GetAllPolygons() #Change the normals for the first polygon in the normal tag set_normals(normalTag, polys[0], polys[0].a, polys[0].b, polys[0].c, polys[0].d)
but polys is a list of CPolygons and therefore polys[0].a etc is an int and not a c4d.Vector.
You need to support c4d.Vector's for normal_a (and so on) as in my example call. -
On 18/03/2014 at 12:05, xxxxxxxx wrote:
I'm using R13.
I'll keep trying to figure it out.
You've posted enough code that I should be able to figure it out eventually. It's just going to take me some time and effort to re-write it so it works for me.Thanks a lot for the help and the code.
-ScottA -
On 18/03/2014 at 13:07, xxxxxxxx wrote:
I think a modification like this should be enough to try it out:
component = [normal.x,normal.y,normal.z] for c in range(0,3) : low_byte, high_byte = float2bytes(component[c])
-
On 18/03/2014 at 14:43, xxxxxxxx wrote:
Yes. That fixed it.
Thanks a lot for the extra effort.I'll post my complete working script code so that way people can at least have something that works that they can cut and paste into their script manager to start off with.
import c4d import math def float2bytes(f) : int_value = int(math.fabs(f * 32000.0)) high_byte = int(int_value / 256) low_byte = int_value - 256 * high_byte if f < 0: high_byte = 255-high_byte low_byte = 255-low_byte return (low_byte,high_byte) def set_normals(normal_tag,polygon,normal_a,normal_b,normal_c,normal_d) : normal_list = [normal_a, normal_b, normal_c, normal_d] normal_buffer = normal_tag.GetLowlevelDataAddressW() vector_size = 6 component_size = 2 for v in range(0,4) : normal = normal_list[v] component = [normal.x, normal.y, normal.z] for c in range(0,3) : low_byte, high_byte = float2bytes(component[c]) normal_buffer[normal_tag.GetDataSize()*polygon+v*vector_size+c*component_size+0] = chr(low_byte) normal_buffer[normal_tag.GetDataSize()*polygon+v*vector_size+c*component_size+1] = chr(high_byte) def main() : obj = doc.GetActiveObject() normal_tag = obj.GetFirstTag() #Assuming the normal tag is the first tag #These four variabls will be used to change the normal values of a polygon normal_a = c4d.Vector(0.0,1.0,0.0) normal_b = c4d.Vector(0.0,1.0,0.0) normal_c = c4d.Vector(0.0,1.0,0.0) normal_d = c4d.Vector(0.0,1.0,0.0) #Set the first polygon normals in the normals tag using the above values set_normals(normal_tag, 0, normal_a, normal_b, normal_c, normal_d) obj.Message(c4d.MSG_UPDATE) c4d.EventAdd() if __name__=='__main__': main()
-ScottA
-
On 19/03/2014 at 03:03, xxxxxxxx wrote:
Hey guys. Thank you very much for your replies and input.
I had time to test reverend's approach and it works. Really cool. Now editing the phong-normals should be a breeze.
Phil