Setting Normals
-
On 21/08/2017 at 12:05, xxxxxxxx wrote:
I got a list of normals and a bunch of polygons:
# get points, normals, faces, uvs indices = gltf_get_accessor(mesh["primitives"][0]["indices"], d, buffer) coords = gltf_get_accessor(mesh["primitives"][0]["attributes"]["POSITION"], d, buffer) uvs = gltf_get_accessor(mesh["primitives"][0]["attributes"]["TEXCOORD_0"], d, buffer) normals = gltf_get_accessor(mesh["primitives"][0]["attributes"]["NORMAL"], d, buffer) faces = [tuple(indices[i:i + 3]) for i in range(0, len(indices), 3)] # create object to hold points obj = c4d.BaseObject(c4d.Opolygon) obj.SetName(mesh["name"]) obj.ResizeObject(len(coords), len(faces)) # add a UV tag to the object uvtag = c4d.UVWTag(len(faces)) obj.InsertTag(uvtag) # add a normal tag to the object ntag = c4d.NormalTag(len(faces)) obj.InsertTag(ntag) # fill points into polygon object for i, v in enumerate(coords) : obj.SetPoint(i, c4d.Vector(v[0], v[1], v[2])) # fill trangles into polygon object and set UV coords for i, f in enumerate(faces) : obj.SetPolygon(i, c4d.CPolygon(f[0], f[1], f[2])) uvtag.SetSlow(i, c4d.Vector(uvs[f[0]][0], uvs[f[0]][1], 0), c4d.Vector(uvs[f[1]][0], uvs[f[1]][1], 0), c4d.Vector(uvs[f[2]][0], uvs[f[2]][1], 0), c4d.Vector()) HOW DO I SET NORMALS? doc.InsertObject(obj)
With generous help for people here, I got pretty much all of it working, except how to set the normal vector for a polygon. The normal tag doesn't seem to have a way to set the normal (unlike the uvtag which has SetSlow)?
-
On 21/08/2017 at 12:11, xxxxxxxx wrote:
Found this after a loooooong search... might be the solution to my problem (nasty)...
https://developers.maxon.net/forum/topic/7713/9752_modifiying-the-normaltag
-
On 21/08/2017 at 12:22, xxxxxxxx wrote:
Ok, that works... even if a bit convoluted...
-
On 22/08/2017 at 05:27, xxxxxxxx wrote:
Here's an old, unfinished script that creates face weighted vertex normals.
You find the method how to set vertex normals inside the main method.import c4d import math from c4d import utils # Calculate a polygons' face normal def CalcFaceNormal(op, polyIndex) : poly = op.GetPolygon(polyIndex) v0 = op.GetPoint(poly.a) v1 = op.GetPoint(poly.b) v3 = op.GetPoint(poly.d) # point c==d, only 3 points needed to calculate a face normal return (v1 - v0).Cross(v3 - v0) # return cross product of point vectors # Calculate face area def CalculateFaceArea(op, polyIndex) : poly = op.GetPolygon(polyIndex) v0 = op.GetPoint(poly.a) v1 = op.GetPoint(poly.b) v2 = op.GetPoint(poly.c) v3 = op.GetPoint(poly.d) if poly.IsTriangle() : return (0.5 * ((v1-v0) % (v2-v0)).GetLength()) else: # if quad return (0.5 * ((v1-v0) % (v2-v0))).GetLength() + (0.5 * ((v3-v2) % (v0-v2)).GetLength()) # Calculate the face angle of the corner and shared edges def CalculateFaceAngle(op, polyIndex, point) : poly = op.GetPolygon(polyIndex) v0 = op.GetPoint(poly.a) v1 = op.GetPoint(poly.b) v3 = op.GetPoint(poly.d) fv0, fv1, fv3 = v0, v1, v3 # TODO: Assemble shared triangles to quads if poly.IsTriangle() : if point == poly.b: fv0 = v1 fv1 = v0 fv3 = v3 if point == poly.d: fv0 = v3 fv1 = v1 fv3 = v0 return utils.VectorAngle((fv0-fv3), (fv0-fv1)) # Calculate a point's average vertex normal, based on neighboring face normals def CalculateVertexNormal(op, pointIndex, polyIndex, nbr) : normal = c4d.Vector() nPolys = nbr.GetPointPolys(pointIndex) #get neighbor poly array for neighborPolyIndex in nPolys: normal = normal + CalcFaceNormal(op, neighborPolyIndex) * CalculateFaceArea(op, neighborPolyIndex) * CalculateFaceAngle(op, neighborPolyIndex, pointIndex) # add up neighbors normals return normal.GetNormalized() # normalized arithmetic middle of neighbored normals def main() : doc.StartUndo() nbr = utils.Neighbor() # involve neighbors tag = c4d.VariableTag(c4d.Tnormal, op.GetPolygonCount()) # create/override tag normals = [] # the HighLevelData Container (sequentially written vectors for each point component) nbr.Init(op) for polyIndex in xrange(op.GetPolygonCount()) : poly = op.GetPolygon(polyIndex) # Calculate vertex normal for each point pointIndexArray = [poly.a, poly.b, poly.c, poly.d] for pointIndex in pointIndexArray: # append vectors sequentially split vNorms = CalculateVertexNormal(op, pointIndex, polyIndex, nbr) normals.append(vNorms.x*32000) normals.append(vNorms.y*32000) normals.append(vNorms.z*32000) op.InsertTag(tag) # Apply tag tag.SetAllHighlevelData(normals) # write normal container to tag c4d.EventAdd() doc.AddUndo(c4d.UNDOTYPE_NEW, tag) if __name__=='__main__': main()
-
On 22/08/2017 at 06:10, xxxxxxxx wrote:
Hi,
just chiming in to add we are aware it is a bit cumbersome to add normals via Python. In C++ the NormalTag has some Get()/Set()/Copy() functions to ease the job. Unfortunately these are not yet available in Python.But at least I can say, we added them to our ToDo list.