示例#1
0
def drawtriangle_strip_worker(params):
    """ 
    Draw a triangle strip using a list of triangle vertices
    and (optional) normals.
    """
    # Note: See the code in class ColorSorter for GL_COLOR_MATERIAL objects.
    
    # piotr 080904 - This method could be optimized by using vertex
    # arrays or VBOs.
    
    (triangles, normals, colors) = params

    # It needs to support two-sided triangles, therefore we disable
    # culling and enable two-sided lighting. These settings have to be 
    # turned back to default setting.
    
    glDisable(GL_CULL_FACE)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)

    # Use color material mode if colors are present.
    
    if colors:
        glEnable(GL_COLOR_MATERIAL)

    glBegin(GL_TRIANGLE_STRIP)
    if normals:
        if colors:
            for p in range(len(triangles)):
                n = normals[p]
                v = triangles[p]
                c = colors[p]
                glNormal3fv(n)
                glColor3fv(c[:3])
                glVertex3fv(v)
        else:
            for p in range(len(triangles)):
                n = normals[p]
                v = triangles[p]
                glNormal3fv(n)
                glVertex3fv(v)
    else:
        for v in triangles:
            glVertex3fv(v)
    glEnd()

    if colors:
        glDisable(GL_COLOR_MATERIAL)

    # piotr 080904 - are these settings really default?

    glEnable(GL_CULL_FACE)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE)

    return
示例#2
0
def drawtriangle_strip_worker(params):
    """
    Draw a triangle strip using a list of triangle vertices
    and (optional) normals.
    """
    # Note: See the code in class ColorSorter for GL_COLOR_MATERIAL objects.

    # piotr 080904 - This method could be optimized by using vertex
    # arrays or VBOs.

    (triangles, normals, colors) = params

    # It needs to support two-sided triangles, therefore we disable
    # culling and enable two-sided lighting. These settings have to be
    # turned back to default setting.

    glDisable(GL_CULL_FACE)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)

    # Use color material mode if colors are present.

    if colors:
        glEnable(GL_COLOR_MATERIAL)

    glBegin(GL_TRIANGLE_STRIP)
    if normals:
        if colors:
            for p in range(len(triangles)):
                n = normals[p]
                v = triangles[p]
                c = colors[p]
                glNormal3fv(n)
                glColor3fv(c[:3])
                glVertex3fv(v)
        else:
            for p in range(len(triangles)):
                n = normals[p]
                v = triangles[p]
                glNormal3fv(n)
                glVertex3fv(v)
    else:
        for v in triangles:
            glVertex3fv(v)
    glEnd()

    if colors:
        glDisable(GL_COLOR_MATERIAL)

    # piotr 080904 - are these settings really default?

    glEnable(GL_CULL_FACE)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE)

    return
示例#3
0
文件: obj.py 项目: OpenWerkplek/pymt
 def enter(self):
     if not self.compat:
         return
     glLightfv(GL_LIGHT0, GL_AMBIENT, (0, 0, 0, 1))
     glLightfv(GL_LIGHT0, GL_DIFFUSE, (.8, .8, .8, 1))
     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (.9, .9, .9))
     glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)
     glEnable(GL_LIGHTING)
     glEnable(GL_LIGHT0)
     glEnable(GL_DEPTH_TEST)
     glColor3f(1, 1, 1)
示例#4
0
 def enter(self):
     if not self.compat:
         return
     glLightfv(GL_LIGHT0, GL_AMBIENT, (0, 0, 0, 1))
     glLightfv(GL_LIGHT0, GL_DIFFUSE, (.8, .8, .8, 1))
     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (.9, .9, .9))
     glLightModelfv(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)
     glEnable(GL_LIGHTING)
     glEnable(GL_LIGHT0)
     glEnable(GL_DEPTH_TEST)
     glColor3f(1, 1, 1)
示例#5
0
def drawtriangle_strip_worker(params):
    """ 
    Draw a triangle strip using a list of triangle vertices
    and (optional) normals.
    """
    (triangles, normals, colors) = params

    #glEnable(GL_LIGHTING)

    glDisable(GL_CULL_FACE)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)

    if colors:
        glEnable(GL_COLOR_MATERIAL)

    #glPolygonMode(GL_FRONT, GL_FILL)
    #glPolygonMode(GL_BACK, GL_FILL)
    # glPolygonOffset(0.0, 10.0)    

    glBegin(GL_TRIANGLE_STRIP)
    if normals:
        if colors:
            for p in range(len(triangles)):
                n = normals[p]
                v = triangles[p]
                c = colors[p]
                glNormal3fv(n)
                glColor3fv(c[:3])
                glVertex3fv(v)
        else:
            for p in range(len(triangles)):
                n = normals[p]
                v = triangles[p]
                glNormal3fv(n)
                glVertex3fv(v)
    else:
        for v in triangles:
            glVertex3fv(v)
    glEnd()

    if colors:
        glDisable(GL_COLOR_MATERIAL)

    glEnable(GL_CULL_FACE)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE)

    return
示例#6
0
def drawtriangle_strip_worker(params):
    """ 
    Draw a triangle strip using a list of triangle vertices
    and (optional) normals.
    """
    (triangles, normals, colors) = params

    #glEnable(GL_LIGHTING)

    glDisable(GL_CULL_FACE)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)

    if colors:
        glEnable(GL_COLOR_MATERIAL)

    #glPolygonMode(GL_FRONT, GL_FILL)
    #glPolygonMode(GL_BACK, GL_FILL)
    # glPolygonOffset(0.0, 10.0)

    glBegin(GL_TRIANGLE_STRIP)
    if normals:
        if colors:
            for p in range(len(triangles)):
                n = normals[p]
                v = triangles[p]
                c = colors[p]
                glNormal3fv(n)
                glColor3fv(c[:3])
                glVertex3fv(v)
        else:
            for p in range(len(triangles)):
                n = normals[p]
                v = triangles[p]
                glNormal3fv(n)
                glVertex3fv(v)
    else:
        for v in triangles:
            glVertex3fv(v)
    glEnd()

    if colors:
        glDisable(GL_COLOR_MATERIAL)

    glEnable(GL_CULL_FACE)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE)

    return
示例#7
0
def draw_vane( bond, a1p, a2p, ord_pi, rad, col ):
    """
    Draw a vane (extending on two opposite sides of the bond axis) [#doc more];
    use ord_pi to determine how intense it is (not yet sure how, maybe by mixing
    in bgcolor??);

    a1p and a2p should be unit vectors perp to bond and no more than 90 degrees
    apart when seen along it; they should be in the bond's coordinate system.

    rad is inner radius of vanes, typically the cylinder radius for the sigma
    bond graphic.

    If col is not boolean false, use it as the vane color; otherwise, use a
    constant color which might be influenced by the pi orbital occupancy.
    """
    from utilities.debug_prefs import debug_pref
    from utilities.debug_prefs import Choice_boolean_True, Choice_boolean_False
    ## twisted = debug_pref('pi vanes/ribbons', Choice_boolean_False)
    # one of ['multicyl','vane','ribbon']
    pi_bond_style = env.prefs[ pibondStyle_prefs_key]
    twisted = (pi_bond_style == 'ribbon')
    poles = debug_pref('pi vanes/poles', Choice_boolean_True)
    draw_outer_edges = debug_pref('pi vanes/draw edges', Choice_boolean_True)
        #bruce 050730 new feature, so that edge-on vanes are still visible
    draw_normals = debug_pref('pi vanes/draw normals', Choice_boolean_False)
    print_vane_params = debug_pref('pi vanes/print params',
                                   Choice_boolean_False)
    if print_vane_params:
        print "draw vane",a1p,vlen(a1p),a2p,vlen(a2p),ord_pi
    if twisted:
        d12 = dot(a1p, a2p)
        ## assert d12 >= 0.0
        if d12 < 0.0:
            d12 = 0.0
        if d12 > 1.0:
            d12 = 1.0
        twist = math.acos(d12) # in radians
            # this is numerically inaccurate (since d12 is) near d12 == 1.0, but
            # that's ok, since it's only compared to threshholds (by ceil())
            # which correspond to d12 values not near 1.0.
            # (#e btw, we could optim the common case (ntwists == 1) by
            #  inverting this comparison to get the equivalent threshhold for
            #  d12.)
        maxtwist = MAXTWIST # debug_pref doesn't yet have a PrefsType for this
        # number of segments needed, to limit each segment's twist to MAXTWIST
        ntwists = max(1, int( math.ceil( twist / maxtwist ) ))
        pass
    if col:
        color = col
    else:
        #bruce 050804: initial test of bond color prefs; inadequate in several
        #  ways #######@@@@@@@
        from foundation.preferences import prefs_context
        prefs = prefs_context()
        from utilities.prefs_constants import bondVaneColor_prefs_key
        #k I hope this color tuple of floats is in the correct prefs format
        color = prefs.get(bondVaneColor_prefs_key)
        # protect following code from color being None (which causes bus error,
        # maybe in PyOpenGL)
        assert len(color) == 3
        
        #####@@@@@ it would be much faster to update this pref (or almost any
        # graphics color pref) if the OpenGL command to set the color was in its
        # own display list, redefined when the redraw starts, and called from
        # inside every other display list that needs it.  Then when you changed
        # it, gl_update would be enough -- the chunk display lists would not
        # need to be remade.
        
        ###@@@ problems include:
        # - being fast enough
        # + dflt should be specified in just one place, and earlier than in this
        #   place, so it can show up in prefs ui before this runs (in fact, even
        #   earlier than when this module is first imported, which might be only
        #   when needed),
        # - existing prefs don't have all the color vars needed (eg no
        #   toolong-highlighted color)
        # - being able to track them only when finally used, not when pulled
        #   into convenience vars before final use -- this might even be an
        #   issue if we precompute a formula from a color-pref, but only count
        #   it as used if that result is used.  (we could decide to track the
        #   formula res as a separate thing, i suppose)
##    a1pos = bond.atom1.posn()
##    a2pos = bond.atom2.posn()
    a1pos, c1, center, c2, a2pos, toolong = bond.geom
    if not toolong:
        c1 = c2 = center # don't know if needed
    x_axis = a2pos - a1pos
    # from 1 to 2.5, with 1 moved out to shrink width according to ord_pi
    width = 1.5 * ord_pi
    inner, outer = 2.5 - width, 2.5
    radius_pairs = [(outer, inner, outer), (-inner, -outer, -outer)]
        # the order within each pair matters, since it affects the polys drawn
        # below being CW or CCW!  but for purposes of edges, we also have to
        # know which one is *really* outer...  thus the third elt (edge_outer)
        # of the tuple.
    # OpenGL code
    #e could optim this to use Numeric calcs and OpenGL vertex array, with
    #  vertex normals and smooth shading, maybe even color ramp of some kind...
    #e want polygon outlines?
    #e want a 1d texture to emphasize the vane's ribbonness & help show ord_pi?
    glDisable(GL_CULL_FACE)
    #bruce 051215 use apply_material(color) instead of glMaterialfv, partly to
    # prevent bug of passing 3-tuple to glMaterialfv, partly to make the vanes
    # appear specular, partly to thereby fix bug 1216 (which was probably caused
    # by not setting specular color here, thus letting it remain from whatever
    # happened to be drawn just before). If we decide vanes should *not* appear
    # specular, we have to actively turn off specular color here rather than
    # ignoring the issue.  One way would be to create and use some new
    # functionality like apply_material(color, specular=False).
    apply_material(color)
    # gl args partly guessed #e should add specularity, shininess...
    ## glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)
        # For vane lighting to be correct, two-sided polygon lighting is
        # required, and every polygon's vertex winding order (CCW) has to match
        # its normal vector, as both are produced by the following code. This
        # means that any changes to the orders of lists of vertices or vectors
        # in this code have to be considered carefully.  But it's ok if a1p and
        # a2p are negated (fortunately, since calling code arbitrarily negates
        # them), since this reverses the poly scan directions in two ways at
        # once (e.g. via pvec and perpvec in the quads case below).  (For ribbon
        # option, it's only ok if they're negated together; for quads case,
        # independent negation is ok.  I'm pretty sure calling code only negates
        # them together.)  [bruce 050725]
    for outer, inner, edge_outer in radius_pairs:
        normals = []
        edgeverts = []
        if twisted:
            glBegin(GL_TRIANGLE_STRIP)
            for i in range(1+ntwists):
                t = float(i) / ntwists # 0.0 to 1.0
                # one minus t (python syntax doesn't let me name it just 1mt)
                _1mt = 1.0 - t
                #e could optimize, not sure it matters
                axispos = _1mt * a1pos + t * a2pos
                # let it get smaller in the middle for large twist (rather than
                # using angles in calc)
                pvec = _1mt * a1p + t * a2p
                # (rationale: shows weakness of bond. real reason: programmer is
                # in a hurry.)
                    #e btw, it might be better to show twist by mismatch of
                    #  larger rectangular vanes, in the middle; and it's faster
                    #  to draw.
                # Could also "* ord_pi" rather than using color, if we worked
                # out proper min radius.
                ## pvec *= (rad * 2.5)
                perpvec = norm(cross(x_axis, pvec))
                # test shows this is needed not only for smoothness, but to make
                # the lighting work at all
                glNormal3fv( perpvec)
                outervert = axispos + pvec * rad * outer
                innervert = axispos + pvec * rad * inner
                glVertex3fv( outervert)
                ## not needed, since the same normal as above
                ## glNormal3fv( perpvec)
                glVertex3fv( innervert)
                #e color? want to smooth-shade it using atom colors, or the
                #  blue/gray for bond order, gray in center?
                if draw_normals:
                    normals.append(( axispos + pvec * rad * edge_outer,
                                     perpvec ))
                if draw_outer_edges:
                    edgeverts.append( axispos + pvec * rad * edge_outer )
            glEnd()
        else:
            glBegin(GL_QUADS)
            for axispos, axispos_c, pvec, normalfactor in \
                    [(a1pos,c1,a1p,-1), (a2pos,c2,a2p,1)]:
                perpvec = norm(cross(x_axis, pvec)) * normalfactor
                glNormal3fv( perpvec)
                glVertex3fv( axispos   + pvec * rad * inner)
                glVertex3fv( axispos   + pvec * rad * outer)
                glVertex3fv( axispos_c + pvec * rad * outer)
                    # This (axispos_c + pvec * rad * outer) would be the corner
                    # we connect by a line, even when not draw_outer_edges, if
                    # outer == edge_outer -- but it might or might not be.
                glVertex3fv( axispos_c + pvec * rad * inner)
                if draw_normals:
                    normals.append(( axispos/2.0 +
                                       axispos_c/2.0 + pvec * rad * edge_outer,
                                     perpvec ))
                if draw_outer_edges:
                    # Kluge to reverse order of first loop body but not second.
                    edgeverts.reverse()
                    edgeverts.append( axispos_c + pvec * rad * edge_outer)
                    edgeverts.append( axispos   + pvec * rad * edge_outer)
                else:
                    # At least connect the halves of each vane, so that twist
                    # doesn't make them look like 2 vanes.
                    edgeverts.append( axispos_c + pvec * rad * edge_outer)
            glEnd()
##            glBegin(GL_LINES)
##            glColor3fv(color)
##            for axispos, axispos_c, pvec in [(a1pos,c1,a1p), (a2pos,c2,a2p)]:
##                glVertex3fv( axispos_c + pvec * rad * outer)
##            glEnd()
        glDisable(GL_LIGHTING) # for lines... don't know if this matters
        if poles:
            glBegin(GL_LINES)
            glColor3fv(color)
            for axispos, pvec in [(a1pos,a1p), (a2pos,a2p)]:
                glVertex3fv( axispos + pvec * rad *  outer)
                glVertex3fv( axispos + pvec * rad * -outer)
            glEnd()
        if normals:
            glBegin(GL_LINES)
            glColor3fv(white)
            for base, vec in normals:
                glVertex3fv(base)
                glVertex3fv(base + vec)
            glEnd()
        if edgeverts:
            glBegin(GL_LINE_STRIP)
            glColor3fv(color)
            for vert in edgeverts:
                glVertex3fv(vert)
            glEnd()
        glEnable(GL_LIGHTING)
    glEnable(GL_CULL_FACE)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE)
    return
示例#8
0
 def light_model(cls, light_model: LightModel, value):
     if isinstance(value, cls.Bool):
         glLightModelf(light_model.value, value.value)
     else:
         glLightModelfv(light_model.value, value)
示例#9
0
def draw_vane( bond, a1p, a2p, ord_pi, rad, col ):
    """
    Draw a vane (extending on two opposite sides of the bond axis) [#doc more];
    use ord_pi to determine how intense it is (not yet sure how, maybe by mixing
    in bgcolor??);

    a1p and a2p should be unit vectors perp to bond and no more than 90 degrees
    apart when seen along it; they should be in the bond's coordinate system.

    rad is inner radius of vanes, typically the cylinder radius for the sigma
    bond graphic.

    If col is not boolean false, use it as the vane color; otherwise, use a
    constant color which might be influenced by the pi orbital occupancy.
    """
    from utilities.debug_prefs import debug_pref
    from utilities.debug_prefs import Choice_boolean_True, Choice_boolean_False
    ## twisted = debug_pref('pi vanes/ribbons', Choice_boolean_False)
    # one of ['multicyl','vane','ribbon']
    pi_bond_style = env.prefs[ pibondStyle_prefs_key]
    twisted = (pi_bond_style == 'ribbon')
    poles = debug_pref('pi vanes/poles', Choice_boolean_True)
    draw_outer_edges = debug_pref('pi vanes/draw edges', Choice_boolean_True)
        #bruce 050730 new feature, so that edge-on vanes are still visible
    draw_normals = debug_pref('pi vanes/draw normals', Choice_boolean_False)
    print_vane_params = debug_pref('pi vanes/print params',
                                   Choice_boolean_False)
    if print_vane_params:
        print "draw vane",a1p,vlen(a1p),a2p,vlen(a2p),ord_pi
    if twisted:
        d12 = dot(a1p, a2p)
        ## assert d12 >= 0.0
        if d12 < 0.0:
            d12 = 0.0
        if d12 > 1.0:
            d12 = 1.0
        twist = math.acos(d12) # in radians
            # this is numerically inaccurate (since d12 is) near d12 == 1.0, but
            # that's ok, since it's only compared to threshholds (by ceil())
            # which correspond to d12 values not near 1.0.
            # (#e btw, we could optim the common case (ntwists == 1) by
            #  inverting this comparison to get the equivalent threshhold for
            #  d12.)
        maxtwist = MAXTWIST # debug_pref doesn't yet have a PrefsType for this
        # number of segments needed, to limit each segment's twist to MAXTWIST
        ntwists = max(1, int( math.ceil( twist / maxtwist ) ))
        pass
    if col:
        color = col
    else:
        #bruce 050804: initial test of bond color prefs; inadequate in several
        #  ways ###@@@
        from foundation.preferences import prefs_context
        prefs = prefs_context()
        from utilities.prefs_constants import bondVaneColor_prefs_key
        #k I hope this color tuple of floats is in the correct prefs format
        color = prefs.get(bondVaneColor_prefs_key)
        # protect following code from color being None (which causes bus error,
        # maybe in PyOpenGL)
        assert len(color) == 3
        
        ###@@@ it would be much faster to update this pref (or almost any
        # graphics color pref) if the OpenGL command to set the color was in its
        # own display list, redefined when the redraw starts, and called from
        # inside every other display list that needs it.  Then when you changed
        # it, gl_update would be enough -- the chunk display lists would not
        # need to be remade.
        
        ###@@@ problems include:
        # - being fast enough
        # + dflt should be specified in just one place, and earlier than in this
        #   place, so it can show up in prefs ui before this runs (in fact, even
        #   earlier than when this module is first imported, which might be only
        #   when needed),
        # - existing prefs don't have all the color vars needed (eg no
        #   toolong-highlighted color)
        # - being able to track them only when finally used, not when pulled
        #   into convenience vars before final use -- this might even be an
        #   issue if we precompute a formula from a color-pref, but only count
        #   it as used if that result is used.  (we could decide to track the
        #   formula res as a separate thing, i suppose)
##    a1pos = bond.atom1.posn()
##    a2pos = bond.atom2.posn()
    a1pos, c1, center, c2, a2pos, toolong = bond.geom
    if not toolong:
        c1 = c2 = center # don't know if needed
    x_axis = a2pos - a1pos
    # from 1 to 2.5, with 1 moved out to shrink width according to ord_pi
    width = 1.5 * ord_pi
    inner, outer = 2.5 - width, 2.5
    radius_pairs = [(outer, inner, outer), (-inner, -outer, -outer)]
        # the order within each pair matters, since it affects the polys drawn
        # below being CW or CCW!  but for purposes of edges, we also have to
        # know which one is *really* outer...  thus the third elt (edge_outer)
        # of the tuple.
    # OpenGL code
    #e could optim this to use Numeric calcs and OpenGL vertex array, with
    #  vertex normals and smooth shading, maybe even color ramp of some kind...
    #e want polygon outlines?
    #e want a 1d texture to emphasize the vane's ribbonness & help show ord_pi?
    glDisable(GL_CULL_FACE)
    #bruce 051215 use apply_material(color) instead of glMaterialfv, partly to
    # prevent bug of passing 3-tuple to glMaterialfv, partly to make the vanes
    # appear specular, partly to thereby fix bug 1216 (which was probably caused
    # by not setting specular color here, thus letting it remain from whatever
    # happened to be drawn just before). If we decide vanes should *not* appear
    # specular, we have to actively turn off specular color here rather than
    # ignoring the issue.  One way would be to create and use some new
    # functionality like apply_material(color, specular=False).
    apply_material(color)
    # gl args partly guessed #e should add specularity, shininess...
    ## glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE)
        # For vane lighting to be correct, two-sided polygon lighting is
        # required, and every polygon's vertex winding order (CCW) has to match
        # its normal vector, as both are produced by the following code. This
        # means that any changes to the orders of lists of vertices or vectors
        # in this code have to be considered carefully.  But it's ok if a1p and
        # a2p are negated (fortunately, since calling code arbitrarily negates
        # them), since this reverses the poly scan directions in two ways at
        # once (e.g. via pvec and perpvec in the quads case below).  (For ribbon
        # option, it's only ok if they're negated together; for quads case,
        # independent negation is ok.  I'm pretty sure calling code only negates
        # them together.)  [bruce 050725]
    for outer, inner, edge_outer in radius_pairs:
        normals = []
        edgeverts = []
        if twisted:
            glBegin(GL_TRIANGLE_STRIP)
            for i in range(1+ntwists):
                t = float(i) / ntwists # 0.0 to 1.0
                # one minus t (python syntax doesn't let me name it just 1mt)
                _1mt = 1.0 - t
                #e could optimize, not sure it matters
                axispos = _1mt * a1pos + t * a2pos
                # let it get smaller in the middle for large twist (rather than
                # using angles in calc)
                pvec = _1mt * a1p + t * a2p
                # (rationale: shows weakness of bond. real reason: programmer is
                # in a hurry.)
                    #e btw, it might be better to show twist by mismatch of
                    #  larger rectangular vanes, in the middle; and it's faster
                    #  to draw.
                # Could also "* ord_pi" rather than using color, if we worked
                # out proper min radius.
                ## pvec *= (rad * 2.5)
                perpvec = norm(cross(x_axis, pvec))
                # test shows this is needed not only for smoothness, but to make
                # the lighting work at all
                glNormal3fv( perpvec)
                outervert = axispos + pvec * rad * outer
                innervert = axispos + pvec * rad * inner
                glVertex3fv( outervert)
                ## not needed, since the same normal as above
                ## glNormal3fv( perpvec)
                glVertex3fv( innervert)
                #e color? want to smooth-shade it using atom colors, or the
                #  blue/gray for bond order, gray in center?
                if draw_normals:
                    normals.append(( axispos + pvec * rad * edge_outer,
                                     perpvec ))
                if draw_outer_edges:
                    edgeverts.append( axispos + pvec * rad * edge_outer )
            glEnd()
        else:
            glBegin(GL_QUADS)
            for axispos, axispos_c, pvec, normalfactor in \
                    [(a1pos,c1,a1p,-1), (a2pos,c2,a2p,1)]:
                perpvec = norm(cross(x_axis, pvec)) * normalfactor
                glNormal3fv( perpvec)
                glVertex3fv( axispos   + pvec * rad * inner)
                glVertex3fv( axispos   + pvec * rad * outer)
                glVertex3fv( axispos_c + pvec * rad * outer)
                    # This (axispos_c + pvec * rad * outer) would be the corner
                    # we connect by a line, even when not draw_outer_edges, if
                    # outer == edge_outer -- but it might or might not be.
                glVertex3fv( axispos_c + pvec * rad * inner)
                if draw_normals:
                    normals.append(( axispos/2.0 +
                                       axispos_c/2.0 + pvec * rad * edge_outer,
                                     perpvec ))
                if draw_outer_edges:
                    # Kluge to reverse order of first loop body but not second.
                    edgeverts.reverse()
                    edgeverts.append( axispos_c + pvec * rad * edge_outer)
                    edgeverts.append( axispos   + pvec * rad * edge_outer)
                else:
                    # At least connect the halves of each vane, so that twist
                    # doesn't make them look like 2 vanes.
                    edgeverts.append( axispos_c + pvec * rad * edge_outer)
            glEnd()
##            glBegin(GL_LINES)
##            glColor3fv(color)
##            for axispos, axispos_c, pvec in [(a1pos,c1,a1p), (a2pos,c2,a2p)]:
##                glVertex3fv( axispos_c + pvec * rad * outer)
##            glEnd()
        glDisable(GL_LIGHTING) # for lines... don't know if this matters
        if poles:
            glBegin(GL_LINES)
            glColor3fv(color)
            for axispos, pvec in [(a1pos,a1p), (a2pos,a2p)]:
                glVertex3fv( axispos + pvec * rad *  outer)
                glVertex3fv( axispos + pvec * rad * -outer)
            glEnd()
        if normals:
            glBegin(GL_LINES)
            glColor3fv(white)
            for base, vec in normals:
                glVertex3fv(base)
                glVertex3fv(base + vec)
            glEnd()
        if edgeverts:
            glBegin(GL_LINE_STRIP)
            glColor3fv(color)
            for vert in edgeverts:
                glVertex3fv(vert)
            glEnd()
        glEnable(GL_LIGHTING)
    glEnable(GL_CULL_FACE)
    glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE)
    return
示例#10
0
def position_mars_3d(temp=None):
    '''
    This is a simple 3D window that shows a spacecraft in MSO coordinates.
    This tool will look for links to the tplot variable that are named either "x/y/z" or "mso_(x/y/z)"
    '''

    # Import 3D functionality from opengl
    try:
        import pyqtgraph.opengl as gl
        from pyqtgraph.Qt import QtGui
        from OpenGL.GL import glLightModelfv, glLightfv, GL_LIGHT0, GL_POSITION, \
            GL_LIGHT_MODEL_AMBIENT, GL_LIGHTING, glEnable, GL_COLOR_MATERIAL, \
            GL_AMBIENT, GL_SPECULAR, GL_DIFFUSE, glMaterial, GL_FRONT_AND_BACK, \
            GL_AMBIENT_AND_DIFFUSE, GL_FRONT, glColorMaterial, GL_PROJECTION, \
            glMatrixMode, glLoadIdentity, glTexParameterf
    except:
        raise (
            "In order to use the 3D position viewing tool you must pip install PyOpenGL"
        )

    # Tell Pytplot about new window
    window = pytplot.tplot_utilities.get_available_qt_window(name='3D_MARS')
    window.resize(1000, 600)
    window.setWindowTitle('3D Mars Window')

    # Defining a new class that keeps track of spacecraft position and moves the
    class PlanetView(gl.GLViewWidget):
        spacecraft_x = 0
        spacecraft_y = 0
        spacecraft_z = 0
        tvar_name = 'temp'  # Store the name of the tplot variable stored, so we know if we need to redraw the orbit

        def paintGL(self, region=None, viewport=None, useItemNames=False):
            glLightfv(GL_LIGHT0, GL_POSITION, [-100000, 0, 0, 0])
            super().paintGL(region=region,
                            viewport=viewport,
                            useItemNames=useItemNames)

    plot1 = PlanetView()

    # Set up the "sun"
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, [.3, .3, .3, 1.0])
    light_position = [-100000, 0, 0, 0]
    glLightfv(GL_LIGHT0, GL_POSITION, light_position)
    glEnable(GL_LIGHTING)
    glEnable(GL_LIGHT0)
    glEnable(GL_COLOR_MATERIAL)
    glLightfv(GL_LIGHT0, GL_AMBIENT, [1, 1, 1, 0])
    glLightfv(GL_LIGHT0, GL_DIFFUSE, [1, 1, 1, 1])
    glLightfv(GL_LIGHT0, GL_SPECULAR, [1, 0, 0, 0])

    # Create Mars and spacecraft icons (assuming spherical spacecraft)
    md = gl.MeshData.sphere(rows=100, cols=220)
    mars = gl.GLMeshItem(meshdata=md,
                         smooth=True,
                         color=(.5, 0, 0, 1),
                         glOptions='opaque')
    mars.translate(0, 0, 0)
    mars.scale(3390, 3390, 3390)
    spacecraft = gl.GLMeshItem(meshdata=md, smooth=True, color=(1, 1, 1, 1))
    spacecraft.translate(plot1.spacecraft_x, plot1.spacecraft_y,
                         plot1.spacecraft_z)

    spacecraft.scale(200, 200, 200)
    orbit_path = gl.GLLinePlotItem()
    plot1.addItem(mars)
    plot1.addItem(spacecraft)
    plot1.addItem(orbit_path)
    glMaterial(GL_FRONT_AND_BACK, GL_SPECULAR, [.5, .5, .5, 1])
    glEnable(GL_COLOR_MATERIAL)
    glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE)

    # Put the planetview plot into the pytplot window
    window.setCentralWidget(plot1)

    # Move around the camera
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    plot1.setModelview()
    plot1.setCameraPosition(distance=30000, azimuth=0, elevation=0)

    # Turn on the window!
    window.show()

    # Define the function that is called on new hover_time updates
    def update(t, name):
        # Move spacecraft back to 0,0,0
        previous_x = plot1.spacecraft_x
        previous_y = plot1.spacecraft_y
        previous_z = plot1.spacecraft_z
        previous_tvar = plot1.tvar_name

        spacecraft.translate(-1 * previous_x, -1 * previous_y, -1 * previous_z)

        # Get the xarray for x/y/z positions of the spacecraft
        if 'x' in pytplot.data_quants[name].attrs['plot_options']['links']:
            x_tvar = pytplot.data_quants[
                pytplot.data_quants[name].attrs['plot_options']['links']['x']]
            y_tvar = pytplot.data_quants[
                pytplot.data_quants[name].attrs['plot_options']['links']['y']]
            z_tvar = pytplot.data_quants[
                pytplot.data_quants[name].attrs['plot_options']['links']['z']]
        elif 'mso_x' in pytplot.data_quants[name].attrs['plot_options'][
                'links']:
            x_tvar = pytplot.data_quants[pytplot.data_quants[name].attrs[
                'plot_options']['links']['mso_x']]
            y_tvar = pytplot.data_quants[pytplot.data_quants[name].attrs[
                'plot_options']['links']['mso_y']]
            z_tvar = pytplot.data_quants[pytplot.data_quants[name].attrs[
                'plot_options']['links']['mso_z']]
        else:
            return

        if name != previous_tvar:
            import numpy as np
            pathasdf = np.array((x_tvar.data, y_tvar.data, z_tvar.data),
                                dtype=float).T
            orbit_path.setData(pos=pathasdf)

        # Get the nearest x/y/z of the hover time
        new_x = x_tvar.sel(time=t, method='nearest').values
        new_y = y_tvar.sel(time=t, method='nearest').values
        new_z = z_tvar.sel(time=t, method='nearest').values

        # Move the spacecraft
        spacecraft.translate(new_x, new_y, new_z)
        plot1.spacecraft_x, plot1.spacecraft_y, plot1.spacecraft_z = new_x, new_y, new_z
        plot1.tvar_name = name
        plot1.paintGL()

    # Register the above update function to the called functions
    pytplot.hover_time.register_listener(update)

    return