Well then that'll be it. Thanks a lot for all the help!
I'll definitely read the manual to get a better idea of each tag.
Here is the final, working code to anyone who reads this thread having the same problems:
def CreateNormalTag(op,polyCnt):
"""
Creates a NormalTag on the passed PolygonObject.
:param op: The PolygonObject that will received a normal Tag.
:type op: c4d.PolygonObject
:return: The created tag.
:rtype: c4d.NormalTag
"""
# Checks if the passed object is a polygon object.
if not isinstance(op, c4d.PolygonObject):
raise TypeError("op is not a c4d.PolygonObject.")
# Creates a Normal Tag in memory only
normalTag = c4d.NormalTag(polyCnt)
if normalTag is None:
raise MemoryError("Failed to creates a normal Tag.")
# Inserts the tag to the passed object
op.InsertTag(normalTag)
# Notifies the object he need to update to take care of the newly created normal tag
op.Message(c4d.MSG_UPDATE)
return normalTag
def WriteNormalTag(tag, normalList):
"""
Write the raw data to a Normal Tag.
:param tag: The Normal Tag to write the data to.
:type tag: c4d.NormalTag
:param normalList: A list with all the raw data.
:type normalList: list[int]
"""
# Retrieves the write buffer array
buffer = tag.GetLowlevelDataAddressW()
if buffer is None:
raise RuntimeError("Failed to retrieves internal write data for the normal tag.")
# Translates list of short int 16 to a BitSeq (string are byte in Python 2.7)
intArray = array.array('h')
intArray.fromlist(normalList)
data = intArray.tostring()
buffer[:len(data)] = data
# Some of the data was read in a binary file/determined earlier but the variable names should be enough to tell what they are
for i in range(surfaceCount):
# Surface triangles count
triCount = read_ushort(c2m)
# Surface Material Name
materialName = read_string(c2m)
tri_vertexgroups = {}
tri_uvgroups = {}
tri_normalgroups = {}
for f in range(triCount):
vertex = vertex1,vertex2,vertex3 # pre-loaded 3 vertex indices for current face
uv = uv1,uv2,uv3 # pre-loaded 3 UV indices for current face
normal = normal1,normal2,normal3 # pre-loaded 3 normal indices for current face
# Add them to a dictionary
tri_vertexgroups[f] = vertex
tri_uvgroups[f] = uv
tri_normalgroups[f] = normal
# Create dictionary for surface's vertices
surface_vertices = {}
# Unique vertex index (used to avoid creating the same vertex twice)
unique_vertex = 0
# Create new poly
mypoly = c4d.BaseObject(c4d.Opolygon) #Create an empty polygon object
mypoly.SetName(materialName)
uv_tag = c4d.UVWTag(triCount)
nrm_tag = CreateNormalTag(mypoly,triCount)
phong_tag = c4d.BaseTag(c4d.Tphong)
phong_tag[c4d.PHONGTAG_PHONG_ANGLELIMIT]=True
phong_tag[c4d.PHONGTAG_PHONG_ANGLE]=c4d.utils.Rad(25.5)
phong_tag[c4d.PHONGTAG_PHONG_USEEDGES]=True
normalList = []
# Loop through number of triangles
for f in range(triCount):
# Load vertices for current triangle from the list of polygon's vertices
tri_vertices = tri_vertexgroups[f]
# Load each vertex of the triangle from a dictionary with all the UVs in the scene using it's index
vertex1 = vertices_positions[tri_vertices[0]]
vertex2 = vertices_positions[tri_vertices[1]]
vertex3 = vertices_positions[tri_vertices[2]]
# Check if vertex was not added already, add if not.
if vertex1 not in surface_vertices:
# Add vertex1 to surface(polygon object)'s dictionary, with a unique index
surface_vertices[vertex1] = unique_vertex
unique_vertex += 1
# Resize our object to allow another point to be created
mypoly.ResizeObject(unique_vertex, triCount)
# Create new point
mypoly.SetPoint(surface_vertices[vertex1],c4d.Vector(vertex1[0],vertex1[1],vertex1[2]))
if vertex2 not in surface_vertices:
surface_vertices[vertex2] = unique_vertex
unique_vertex += 1
mypoly.ResizeObject(unique_vertex, triCount)
mypoly.SetPoint(surface_vertices[vertex2],c4d.Vector(vertex2[0],vertex2[1],vertex2[2]))
if vertex3 not in surface_vertices:
surface_vertices[vertex3] = unique_vertex
unique_vertex += 1
mypoly.ResizeObject(unique_vertex, triCount)
mypoly.SetPoint(surface_vertices[vertex3],c4d.Vector(vertex3[0],vertex3[1],vertex3[2]))
# Load UVs for current triangle from the list of polygon's UVs
tri_uvs = tri_uvgroups[f]
# Load each UV of the triangle from a dictionary with all the UVs in the scene using it's index
uv1 = vertices_uvs[tri_uvs[0]]
uv2 = vertices_uvs[tri_uvs[1]]
uv3 = vertices_uvs[tri_uvs[2]]
# Create polygon(triangle)
mypoly.SetPolygon(f, c4d.CPolygon(surface_vertices[vertex1],surface_vertices[vertex2],surface_vertices[vertex3]))
# Add our UV data to the UV tag
uv_tag.SetSlow(f, c4d.Vector(uv1[0], uv1[1], 0),
c4d.Vector(uv2[0], uv2[1], 0),
c4d.Vector(uv3[0], uv3[1], 0),
c4d.Vector(0,0,0))
# Load normals for current triangle from the list of polygon's normals
tri_normals = tri_normalgroups[f]
# Load each normal of the triangle from a dictionary with all the normals in the scene using it's index
normal1 = vertices_normals[tri_normals[0]] # Vector3 of normal direction
normal2 = vertices_normals[tri_normals[1]]
normal3 = vertices_normals[tri_normals[2]]
normal4 = [0.0, 0.0, 0.0] # Even if it's a Tri, you should pass a value.
# Add normals to normalList
normalList.extend(normal1)
normalList.extend(normal2)
normalList.extend(normal3)
normalList.extend(normal4)
# Maps data from float to int16 value
normalListToSet = [int(normal * 32000.0) for normal in normalList]
# Writes the previous list to the normal tag.
WriteNormalTag(nrm_tag, normalListToSet)
doc.InsertObject(mypoly,None,None)
mypoly.Message(c4d.MSG_UPDATE)
mypoly.InsertTag(uv_tag)
mypoly.Message(c4d.MSG_UPDATE)
mypoly.InsertTag(phong_tag)
mypoly.Message(c4d.MSG_UPDATE)
c4d.EventAdd()
Thank you once again Maxime, your help is appreciated!