class_docstr: Class for storing and operating on 3D mesh data. May contain:
  
    - list of vertex locations
    - list of edges
    - list of triangles
    - colors per vertex, edge, or tri
    - normals per vertex or tri
  
  This class handles conversion between the standard [list of vertexes, list of faces]
  format (suitable for use with glDrawElements) and 'indexed' [list of vertexes] format
  (suitable for use with glDrawArrays). It will automatically compute face normal
  vectors as well as averaged vertex normal vectors. 
  
  The class attempts to be as efficient as possible in caching conversion results and
  avoiding unnecessary conversions.
class_docstr_tok: ["Class","for","storing","and","operating","on","3D","mesh","data",".","May","contain",":","-","list","of","vertex","locations","-","list","of","edges","-","list","of","triangles","-","colors","per","vertex",",","edge",",","or","tri","-","normals","per","vertex","or","tri","This","class","handles","conversion","between","the","standard","[","list","of","vertexes",",","list","of","faces","]","format","(","suitable","for","use","with","glDrawElements",")","and","'indexed","'","[","list","of","vertexes","]","format","(","suitable","for","use","with","glDrawArrays",")",".","It","will","automatically","compute","face","normal","vectors","as","well","as","averaged","vertex","normal","vectors",".","The","class","attempts","to","be","as","efficient","as","possible","in","caching","conversion","results","and","avoiding","unnecessary","conversions","."]
docstr: Return a MeshData instance with vertexes and faces computed
  for a spherical surface.
docstr_tok: ["Return","a","MeshData","instance","with","vertexes","and","faces","computed","for","a","spherical","surface","."]
code: def sphere(rows, cols, radius=1.0, offset=True):
      """
      Return a MeshData instance with vertexes and faces computed
      for a spherical surface.
      """
      verts = np.empty((rows + 1, cols, 3), dtype=float)
  
      ## compute vertexes
      phi = (np.arange(rows + 1) * np.pi / rows).reshape(rows + 1, 1)
      s = radius * np.sin(phi)
      verts[..., 2] = radius * np.cos(phi)
      th = (np.arange(cols) * 2 * np.pi / cols).reshape(1, cols)
      if offset:
          th = th + (
              (np.pi / cols) * np.arange(rows + 1).reshape(rows + 1, 1)
          )  ## rotate each row by 1/2 column
      verts[..., 0] = s * np.cos(th)
      verts[..., 1] = s * np.sin(th)
      verts = verts.reshape((rows + 1) * cols, 3)[
          cols - 1 : -(cols - 1)
      ]  ## remove redundant vertexes from top and bottom
  
      ## compute faces
      faces = np.empty((rows * cols * 2, 3), dtype=np.uint)
      rowtemplate1 = (
          (np.arange(cols).reshape(cols, 1) + np.array([[0, 1, 0]]))
          % cols
      ) + np.array([[0, 0, cols]])
      rowtemplate2 = (
          (np.arange(cols).reshape(cols, 1) + np.array([[0, 1, 1]]))
          % cols
      ) + np.array([[cols, 0, cols]])
      for row in range(rows):
          start = row * cols * 2
          faces[start : start + cols] = rowtemplate1 + row * cols
          faces[start + cols : start + (cols * 2)] = (
              rowtemplate2 + row * cols
          )
      faces = faces[
          cols:-cols
      ]  ## cut off zero-area triangles at top and bottom
  
      ## adjust for redundant vertexes that were removed from top and bottom
      vmin = cols - 1
      faces[faces < vmin] = vmin
      faces -= vmin
      vmax = verts.shape[0] - 1
      faces[faces > vmax] = vmax
  
      return MeshData(vertexes=verts, faces=faces)
  
imports: import numpy
  from ..Qt import QtGui
label_desc: Use image node_id 25 for calling the MeshData obj's underlying member method code with example usage: obj.sphere(rows, cols, radius, offset) and returns: MeshData