Example #1
0
def build_normalPerVertex( vertices, creaseAngle, vertexArray=None ):
    '''Create a normal vector using creaseAngle to determine smoothing

    Note: the semantics of normalPerVertex requires using expanded
    (i.e. tessellated) values, as the generated normals are *not*
    supposed to be applied to each vertex, but instead to each
    *use* of each vertex (i.e. each triangle's ref to the vertex
    has a potentially different normal)
    
    vertices -- list of vertex objects in rendering order (triangles)
    creaseAngle -- radian angle above which faces do not smooth.
    vertexArray -- x*3*3 array of coordinates expanded into a flat
        data-array, if not provided, generated from vertices
    '''
    if vertexArray is None:
        vertexArray = array([vertex.point for vertex in vertices],'f')
    faceNormals = triangleutilities.normalPerFace( vertexArray )
    vertexNormals = repeat(faceNormals,[3]*len(faceNormals),0)
    faceNormals = array(vertexNormals[:])
    items = {}
    for index in range( len( vertices)):
        try:
            items.setdefault( vertices[index].coordIndex, []).append( index )
        except TypeError, err:
            print vertices[index]
            print type(vertices[index].coordIndex),vertices[index].coordIndex
            raise
Example #2
0
def build_normalPerVertex(vertices, creaseAngle, vertexArray=None):
    '''Create a normal vector using creaseAngle to determine smoothing

    Note: the semantics of normalPerVertex requires using expanded
    (i.e. tessellated) values, as the generated normals are *not*
    supposed to be applied to each vertex, but instead to each
    *use* of each vertex (i.e. each triangle's ref to the vertex
    has a potentially different normal)
    
    vertices -- list of vertex objects in rendering order (triangles)
    creaseAngle -- radian angle above which faces do not smooth.
    vertexArray -- x*3*3 array of coordinates expanded into a flat
        data-array, if not provided, generated from vertices
    '''
    if vertexArray is None:
        vertexArray = array([vertex.point for vertex in vertices], 'f')
    faceNormals = triangleutilities.normalPerFace(vertexArray)
    vertexNormals = repeat(faceNormals, [3] * len(faceNormals), 0)
    faceNormals = array(vertexNormals[:])
    items = {}
    for index in range(len(vertices)):
        try:
            items.setdefault(vertices[index].coordIndex, []).append(index)
        except TypeError, err:
            print vertices[index]
            print type(vertices[index].coordIndex), vertices[index].coordIndex
            raise
Example #3
0
    def __init__(self, points, normals=None, ccw=1):
        """Initialize the EdgeSet

        points -- n*3 array of points, n%3 == 0, where each
            set of three points defines a single triangle in
            ccw winding
        normals -- optional array of per-triangle normals, will
            be calculated if necessary
        ccw -- boolean indicating whether counter-clock-wise
            winding is to be used (normal OpenGL/VRML winding)
            if false, then use clockwise winding
            (Note that this has never been tested, as I don't
            have any cw geometry around to test with, and haven't
            felt energetic enough to work around the standard
            tools to make any)
        """
        self.volumes = weakref.WeakKeyDictionary()
        self.ccw = ccw

        self.points = points
        self.normals = triangleutilities.normalPerFace(points, ccw=ccw)
        self.points_to_edges()
Example #4
0
    def __init__( self, points, normals=None, ccw = 1 ):
        """Initialize the EdgeSet

        points -- n*3 array of points, n%3 == 0, where each
            set of three points defines a single triangle in
            ccw winding
        normals -- optional array of per-triangle normals, will
            be calculated if necessary
        ccw -- boolean indicating whether counter-clock-wise
            winding is to be used (normal OpenGL/VRML winding)
            if false, then use clockwise winding
            (Note that this has never been tested, as I don't
            have any cw geometry around to test with, and haven't
            felt energetic enough to work around the standard
            tools to make any)
        """
        self.volumes = weakref.WeakKeyDictionary()
        self.ccw = ccw
        
        self.points = points
        self.normals = triangleutilities.normalPerFace( points, ccw=ccw )
        self.points_to_edges()
Example #5
0
def build_normalPerVertex(vertices, creaseAngle, vertexArray=None):
    '''Create a normal vector using creaseAngle to determine smoothing

    Note: the semantics of normalPerVertex requires using expanded
    (i.e. tessellated) values, as the generated normals are *not*
    supposed to be applied to each vertex, but instead to each
    *use* of each vertex (i.e. each triangle's ref to the vertex
    has a potentially different normal)
    
    vertices -- list of vertex objects in rendering order (triangles)
    creaseAngle -- radian angle above which faces do not smooth.
    vertexArray -- x*3*3 array of coordinates expanded into a flat
        data-array, if not provided, generated from vertices
    '''
    if vertexArray is None:
        vertexArray = array([vertex.point for vertex in vertices], 'f')
    faceNormals = triangleutilities.normalPerFace(vertexArray)
    vertexNormals = repeat(faceNormals, [3] * len(faceNormals), 0)
    faceNormals = array(vertexNormals[:])
    items = {}
    for index in range(len(vertices)):
        try:
            items.setdefault(vertices[index].coordIndex, []).append(index)
        except TypeError as err:
            print vertices[index]
            print type(vertices[index].coordIndex), vertices[index].coordIndex
            raise
    #   verticies. We use ones instead of zeros because each face
    #   contributes to its own corner.  Note: will be promoted to float
    #   during the final division
    counts = ones((len(vertexNormals), ), 'f')
    for vertexSet in items.values():
        # For each primary user (triangle corner)
        for index in range(len(vertexSet)):
            primaryNormal = faceNormals[vertexSet[index]]
            # check to see if any of the remaining triangles should
            # be blended with this one
            for innerindex in range(index + 1, len(vertexSet)):
                secondaryNormal = faceNormals[vertexSet[innerindex]]
                # if angle < creaseAngle... should calculate
                # cos(creaseAngle) instead of using arccos each time
                try:
                    angle = arccos(dot(primaryNormal, secondaryNormal))
                except ValueError as err:  # arccos of equal vectors goes kablooie
                    angle = 0
                if angle < creaseAngle:
                    #add to each other's cummulative total (in place)
                    add(vertexNormals[vertexSet[index]], secondaryNormal,
                        vertexNormals[vertexSet[index]])  # add in place
                    add(vertexNormals[vertexSet[innerindex]], primaryNormal,
                        vertexNormals[vertexSet[innerindex]])  # add in place
                    # and increment the element counts
                    counts[vertexSet[index]] = counts[vertexSet[index]] + 1
                    counts[vertexSet[innerindex]] = counts[
                        vertexSet[innerindex]] + 1
    # reshape counts to allow for in-place division...
    counts.shape = (-1, 1)
    # divide in place, completing the averaging (and thereby hopefully
    # re-normalising the Normal vectors)
    divide(vertexNormals, counts, vertexNormals)
    return vertexNormals
Example #6
0
 def compile(
     self,
     visible=1,
     lit=1,
     textured=1,
     transparent=0,
     mode=None,
 ):
     """Compile to an opaque textured display-list"""
     dl = displaylist.DisplayList()
     dl.start()
     try:
         if (not self.target.normal) or (
                 self.target.normal and not len(self.target.normal.vector)):
             # need to generate per-face or per-vertex-use vectors,
             # require tessellation!
             vertices = self.tessellate()
             if not vertices:
                 return None
             if self.target.normalPerVertex:
                 normalArray = build_normalPerVertex(
                     vertices, self.target.creaseAngle)
                 normalStep = 1
             else:
                 normalArray = triangleutilities.normalPerFace(vertexArray)
                 normalArray = repeat(normalArray, [3] * len(normalArray),
                                      0)
                 normalStep = 3
             glBegin(GL_TRIANGLES)
             if self.target.DEBUG_DRAW_NORMALS:
                 normalValues = []
             try:
                 normalIndex = -1
                 for vIndex in xrange(len(vertices)):
                     vertex = vertices[vIndex]
                     if vIndex % normalStep == 0:
                         normalIndex += 1
                     glNormal3dv(normalArray[normalIndex])
                     if vertex.color is not None:
                         glColor3dv(vertex.color)
                     if vertex.textureCoordinate is not None:
                         glTexCoord2dv(vertex.textureCoordinate)
                     glVertex3dv(vertex.point)
                     if self.target.DEBUG_DRAW_NORMALS:
                         normalValues.append(
                             (vertex.point,
                              vertex.point + normalArray[normalIndex]))
             finally:
                 glEnd()
             if self.target.DEBUG_DRAW_NORMALS:
                 glBegin(GL_LINES)
                 try:
                     for (v, n) in normalValues:
                         glColor3f(1, 0, 0)
                         glVertex3dv(v)
                         glColor3f(0, 1, 0)
                         glVertex3dv(n)
                 finally:
                     glEnd()
         else:
             # already has normals, can render without tessellation
             for polygon in self.polygons():
                 if len(polygon) == 3:
                     glBegin(GL_TRIANGLES)
                 elif len(polygon) == 4:
                     glBegin(GL_QUADS)
                 elif len(polygon) < 3:
                     continue
                 else:
                     glBegin(GL_POLYGON)
                 try:
                     for vertex in polygon:
                         if vertex.normal is not None:
                             glNormal3dv(vertex.normal)
                         if vertex.color is not None:
                             glColor3dv(vertex.color)
                         if vertex.textureCoordinate is not None:
                             glTexCoord2dv(vertex.textureCoordinate)
                         glVertex3dv(vertex.point)
                 finally:
                     glEnd()
         return DisplayListRenderer(dl)
     finally:
         dl.end()
Example #7
0
    def compile(
        self,
        visible=1,
        lit=1,
        textured=1,
        transparent=0,
        mode=None,
    ):
        """Compile the rendering structures for an ArrayGeometry version of IFS
        
        XXX Should redo to cache like so...
        cache tessellated triangle indices
            if any indices change, need to re-calculate everything
            coord -> [ pointIndices ], [ calcualtedNormals ]
            normal -> [ normalIndices ]
            
            when points change, just re-calculate:
                expanded-normals (if we are calculating normals)
                expanded-points
            when normals change (explicit normal/indices)
                expanded-normals
            
            fully-expanded normal, texCooord, and color
        """
        ### XXX should store normals regardless of "lit" field and discard lit
        # XXX check to see if we are all using the same indices,
        # if so, we can possibly use IndexedPolygons instead
        # of IndexedFaceSet for rendering...
        vertices = self.tessellate()

        # vertices is now a list of vertices such that
        # every three vertices represents a single triangle
        # good time to build normals if required...
        vertexArray = array([vertex.point for vertex in vertices], 'f')
        if len(vertexArray) == 0:
            return DUMMY_RENDER
        else:
            if (not self.target.normal) or (not len(
                    self.target.normal.vector)):
                # need to calculate normals
                if self.target.normalPerVertex:
                    normalArray = build_normalPerVertex(
                        vertices, self.target.creaseAngle, vertexArray)
                else:
                    normalArray = triangleutilities.normalPerFace(vertexArray)
                    normalArray = repeat(normalArray, [3] * len(normalArray),
                                         0)
            else:
                normalArray = []
                for vertex in vertices:
                    if vertex.normal is not None:
                        normalArray.append(vertex.normal)
                    elif normalArray:
                        normalArray.append(normalArray[-1])
                    else:
                        normalArray.append((0, 0, 1))
                normalArray = array(normalArray, 'f')

            if self.target.color and len(self.target.color.color):
                try:
                    colorArray = array([vertex.color for vertex in vertices],
                                       'f')
                except TypeError:
                    colorArray = None
                    log.warn(
                        """%s tessellation appears to have created invalid color for tesselated vertex""",
                        self.target)
            else:
                colorArray = None
            if self.target.texCoord and len(self.target.texCoord.point):
                textureCoordinateArray = array(
                    [vertex.textureCoordinate for vertex in vertices], 'f')
            else:
                textureCoordinateArray = None
            log.debug(
                'Arrays: \nvertex -- %s\nnormal -- %s',
                vertexArray,
                normalArray,
            )
            ag = arraygeometry.ArrayGeometry(
                vertexArray,
                colorArray,
                normalArray,
                textureCoordinateArray,
                objectType=GL_TRIANGLES,
                ccw=self.target.ccw,
                solid=self.target.solid,
            )
            return ag
Example #8
0
 def compile( 
     self,
     visible = 1,
     lit = 1, 
     textured = 1,
     transparent = 0,
     mode=None,
 ):
     """Compile to an opaque textured display-list"""
     dl = displaylist.DisplayList()
     dl.start()
     try:
         if (not self.target.normal) or (self.target.normal and not len(self.target.normal.vector)):
             # need to generate per-face or per-vertex-use vectors,
             # require tessellation!
             vertices = self.tessellate()
             if not vertices:
                 return None
             if self.target.normalPerVertex:
                 normalArray = build_normalPerVertex(
                     vertices, self.target.creaseAngle
                 )
                 normalStep = 1
             else:
                 normalArray = triangleutilities.normalPerFace( vertexArray)
                 normalArray = repeat( normalArray,[3]*len(normalArray),0)
                 normalStep = 3
             glBegin( GL_TRIANGLES )
             if self.target.DEBUG_DRAW_NORMALS:
                 normalValues = []
             try:
                 normalIndex = -1
                 for vIndex in xrange(len(vertices)):
                     vertex = vertices[vIndex]
                     if vIndex % normalStep == 0:
                         normalIndex += 1
                     glNormal3dv( normalArray[normalIndex] )
                     if vertex.color is not None:
                         glColor3dv( vertex.color )
                     if vertex.textureCoordinate is not None:
                         glTexCoord2dv( vertex.textureCoordinate )
                     glVertex3dv( vertex.point )
                     if self.target.DEBUG_DRAW_NORMALS:
                         normalValues.append( (vertex.point, vertex.point+normalArray[normalIndex]) )
             finally:
                 glEnd()
             if self.target.DEBUG_DRAW_NORMALS:
                 glBegin( GL_LINES )
                 try:
                     for (v,n) in normalValues:
                         glColor3f( 1,0,0)
                         glVertex3dv( v )
                         glColor3f( 0,1,0)
                         glVertex3dv( n )
                 finally:
                     glEnd()
         else:
             # already has normals, can render without tessellation
             for polygon in self.polygons():
                 if len(polygon) == 3:
                     glBegin( GL_TRIANGLES )
                 elif len(polygon) == 4:
                     glBegin( GL_QUADS )
                 elif len(polygon) < 3:
                     continue
                 else:
                     glBegin( GL_POLYGON )
                 try:
                     for vertex in polygon:
                         if vertex.normal is not None:
                             glNormal3dv( vertex.normal )
                         if vertex.color is not None:
                             glColor3dv( vertex.color )
                         if vertex.textureCoordinate is not None:
                             glTexCoord2dv( vertex.textureCoordinate )
                         glVertex3dv( vertex.point )
                 finally:
                     glEnd()
         return DisplayListRenderer( dl )
     finally:
         dl.end()
Example #9
0
 def compile(
     self,
     visible = 1,
     lit = 1, 
     textured = 1,
     transparent = 0,
     mode=None,
 ):
     """Compile the rendering structures for an ArrayGeometry version of IFS
     
     XXX Should redo to cache like so...
     cache tessellated triangle indices
         if any indices change, need to re-calculate everything
         coord -> [ pointIndices ], [ calcualtedNormals ]
         normal -> [ normalIndices ]
         
         when points change, just re-calculate:
             expanded-normals (if we are calculating normals)
             expanded-points
         when normals change (explicit normal/indices)
             expanded-normals
         
         fully-expanded normal, texCooord, and color
     """
     ### XXX should store normals regardless of "lit" field and discard lit
     # XXX check to see if we are all using the same indices,
     # if so, we can possibly use IndexedPolygons instead
     # of IndexedFaceSet for rendering...
     vertices = self.tessellate()
     
     # vertices is now a list of vertices such that
     # every three vertices represents a single triangle
     # good time to build normals if required...
     vertexArray = array([vertex.point for vertex in vertices],'f')
     if len(vertexArray) == 0:
         return DUMMY_RENDER
     else:
         if (not self.target.normal) or (not len(self.target.normal.vector)):
             # need to calculate normals
             if self.target.normalPerVertex:
                 normalArray = build_normalPerVertex(
                     vertices, self.target.creaseAngle, vertexArray
                 )
             else:
                 normalArray = triangleutilities.normalPerFace( vertexArray)
                 normalArray = repeat( normalArray,[3]*len(normalArray), 0)
         else:
             normalArray = []
             for vertex in vertices:
                 if vertex.normal is not None:
                     normalArray.append( vertex.normal )
                 elif normalArray:
                     normalArray.append( normalArray[-1] )
                 else:
                     normalArray.append( (0,0,1))
             normalArray = array(normalArray,'f')
         
         if self.target.color and len(self.target.color.color):
             try:
                 colorArray = array([vertex.color for vertex in vertices],'f')
             except TypeError:
                 colorArray = None
                 log.warn("""%s tessellation appears to have created invalid color for tesselated vertex""",self.target)
         else:
             colorArray = None
         if self.target.texCoord and len(self.target.texCoord.point):
             textureCoordinateArray = array([vertex.textureCoordinate for vertex in vertices],'f')
         else:
             textureCoordinateArray = None
         log.debug(
             'Arrays: \nvertex -- %s\nnormal -- %s',
             vertexArray, normalArray,
         )
         ag = arraygeometry.ArrayGeometry(
             vertexArray,
             colorArray,
             normalArray,
             textureCoordinateArray,
             objectType= GL_TRIANGLES,
             ccw = self.target.ccw,
             solid = self.target.solid,
         )
         return ag