Copying attributes

Bengt Richter bokr at oz.net
Sat Jul 23 14:30:29 EDT 2005


On Thu, 21 Jul 2005 00:45:12 +0200, red <red at redplanet.com> wrote:

>Hi,
>
>I'm writing a script for Blender and need to build a face array. My
>engine needs that all faces must be triangles, so I convert quads to 
>triangles by dividing them into two triangles. Here is the function:
>
>def build_face_table(mesh):
>	face_table = {}
        # face_table = [] ??
Irrelevant nit: Why a dict? You seem to be building it with all the keys as integers of xrange(last_i),
in which case appending a face_table list to build it and later accessing face_table[key]
will go faster than your current dict. OTOH, if you will be deleting various elements later,
your dict may be best.

>	i = 0
>	for f in mesh.faces:
>		if len(f.v) == 3:	# triangle
>			face_table[i] = f
                        # face_table.append(f)  # no need for i counting
>			i += 1
>		elif len(f.v) == 4:	# quad
>			f1 = NMesh.Face()
>			f2 = NMesh.Face()
>
>			f1.mat = f.mat
>##			f1.normal = copy.deepcopy(f.normal)
>			f1.normal = NMesh.Vert(f.normal[0], f.normal[1], f.normal[2])
f is a quad at this point, right? So unless the quad is restricted to a plane, it couldn't
have a normal in general. Could that be it? BTW, if it is not a plane, one choice of diagonal
may be better than the other in getting two triangles that fit the underlying 3D surface best.

If there is a normal, why wouldn't ft.normal = f.normal[::] work?
Is normal more than a 3-tuple or list to record unit vector components in some coordinate system?

>			f1.v.append(f.v[0])
>			f1.v.append(f.v[1])
>			f1.v.append(f.v[2])
Why append, and is there restricted property magic behind f1.v so that plain old
                        f1.v = f.v[:3]
wouldn't work?
                        # or f1.v = [f.v[0], f.v[1], f.v[2]] if you want to be consistent with f2 below
>
>			f2.mat = f.mat
                        # f2.normal = ?? # could this face be picked up later indirectly and cause the missing normal exception?

>			f2.v.append(f.v[2])
>			f2.v.append(f.v[3])
>			f2.v.append(f.v[0])
Why appends? Does f2.v ever grow beyond 3 items? E.g.,
                        f2.v = [f.v[2], f.v[3], f.v[0]]  # are quad vertices listed clockwise or ccw and
                                                         # are triangles in a sequence totally independent, or
                                                         # is there some systematic vertex sharing in the order
                                                         # that something might depend on, or benefit optimization-wise from?

>
>			face_table[i] = f1
                        #face_table.append(f1) ??
>			i += 1
>			face_table[i] = f2
                        #face_table.append(f2) ??
>			i += 1
>		else:
>			message = "Can't build face from 2 vertices."
                        Why is len(f.v)>4 not just a 3D surface point cluster, in which case it might
                        be possible to find an internal point to slice radiating triangles from. E.g.,
                        imagine an almost-plane small pentagon on a large sphere, and slice from its "center"
                        to each peripheral pair of vertices to make triangles.
>			Draw.PupMenu("Face Table Error%t|"+message)
>			return
>	return face_table
        # do you need it as a dict? Unless you modify it, a list will get you
        # the same elements as your dict by writing face_table[some_index]

If you need to iterate and have both index key and value, you can use your dict like
        for i, face in sorted(face_table.items()): # leave out sorted call if order does not matter
            # ...
or use the more efficient list version of face_table like
        for i, face in enumerate(facetable): # will naturally be in sort order
            # ...
>
>Everything seems be ok, but i'm getting:
>
>Traceback (most recent call last):
>    File "<string>", line 169, in write
>    File "<string>", line 102, in build_face_table
>AttributeError: normal
>
>I was wondering why? Though the face has an attribute called "normal"! 
>Just simply test:
>
>nv = f.normal
>
>and it works! But why my new faces (f1 and f2) no?
Did it work on a quad face? What about putting in a debug print before places you use
f.normal, e.g.
    assert hasattr(f, 'normal'), 'This "f"\n----\n%r\n----\ndid not have a normal attribute!!' % f

If f.repr doesn't give you enough info, you can format something better in the assert message string.
>
>Greetings.
>
>-- 
>_red ____ _ ____ ____ __ _

BTW, I don't know Blender at all, just reading between the lines ;-)
Hope I triggered a useful thought.

Regards,
Bengt Richter



More information about the Python-list mailing list