Ejemplo n.º 1
0
def loadFileOBJ(model, fileName):
  """Loads an obj file with associated mtl file to produce Buffer object
  as part of a Shape. Arguments:
    *model*
      Model object to add to.
    *fileName*
      Path and name of obj file relative to top directory.
  """
  model.coordinateSystem = "Y-up"
  model.parent = None
  model.childModel = [] # don't really need parent and child pointers but will speed up traversing tree
  model.vNormal = False
  model.vGroup = {} # holds the information for each vertex group

  # read in the file and parse into some arrays

  filePath = os.path.split(os.path.abspath(fileName))[0]
  print(filePath)
  f = open(fileName, 'r')

  vertices = []
  normals = []
  uvs = []

  faces = {}

  materials = {}
  material = ""
  mcounter = 0
  mcurrent = 0
  numv = [] #number of vertices for each material (nb each vertex will have three coords)
  numi = [] #number of indices (triangle corners) for each material

  mtllib = ""

  # current face state
  group = 0
  objct = 0
  smooth = 0

  for l in f:
    chunks = l.split()
    if len(chunks) > 0:

      # Vertices as (x,y,z) coordinates
      # v 0.123 0.234 0.345
      if chunks[0] == "v" and len(chunks) == 4:
        x = float(chunks[1])
        y = float(chunks[2])
        z = -float(chunks[3]) # z direction away in gl es 2.0 shaders
        vertices.append((x, y, z))

      # Normals in (x, y, z) form; normals might not be unit
      # vn 0.707 0.000 0.707
      if chunks[0] == "vn" and len(chunks) == 4:
        x = float(chunks[1])
        y = float(chunks[2])
        z = -float(chunks[3]) # z direction away in gl es 2.0 shaders
        normals.append((x, y, z))

      # Texture coordinates in (u,v)
      # vt 0.500 -1.352
      if chunks[0] == "vt" and len(chunks) >= 3:
        u = float(chunks[1])
        v = float(chunks[2])
        uvs.append((u, v))

      # Face
      if chunks[0] == "f" and len(chunks) >= 4:
        vertex_index = []
        uv_index = []
        normal_index = []


        # Precompute vert / normal / uv lists
        # for negative index lookup
        vertlen = len(vertices) + 1
        normlen = len(normals) + 1
        uvlen = len(uvs) + 1

        if len(numv) < (mcurrent+1): numv.append(0)
        if len(numi) < (mcurrent+1): numi.append(0)

        for v in chunks[1:]:
          numv[mcurrent] += 1
          numi[mcurrent] += 3
          vertex = parse_vertex(v)
          if vertex['v']:
            if vertex['v'] < 0:
              vertex['v'] += vertlen
            vertex_index.append(vertex['v'])
          if vertex['t']:
            if vertex['t'] < 0:
              vertex['t'] += uvlen
            uv_index.append(vertex['t'])
          if vertex['n']:
            if vertex['n'] < 0:
              vertex['n'] += normlen
            normal_index.append(vertex['n'])
        numi[mcurrent] -= 6 # number of corners of triangle = (n-2)*3 where n is the number of corners of face
        if not mcurrent in faces: faces[mcurrent] = []

        faces[mcurrent].append({
          'vertex':vertex_index,
          'uv':uv_index,
          'normal':normal_index,

          'group':group,
          'object':objct,
          'smooth':smooth,
          })

      # Group
      if chunks[0] == "g" and len(chunks) == 2:
        group = chunks[1]

      # Object
      if chunks[0] == "o" and len(chunks) == 2:
        objct = chunks[1]

      # Materials definition
      if chunks[0] == "mtllib" and len(chunks) == 2:
        mtllib = chunks[1]

      # Material
      if chunks[0] == "usemtl":
        if len(chunks) > 1:
          material = chunks[1]
        else:
          material = ""
        if not material in materials:
          mcurrent = mcounter
          materials[material] = mcounter
          mcounter += 1
        else:
          mcurrent = materials[material]

      # Smooth shading
      if chunks[0] == "s" and len(chunks) == 2:
        smooth = chunks[1]
  if VERBOSE:
    print("materials:  ", materials)
    print("numv: ", numv)

  for g in faces:
    numv[g] -= 1
    numi[g] -= 1

    g_vertices = []
    g_normals = []
    g_tex_coords = []
    g_indices = []
    i = 0 # vertex counter in this material
    if VERBOSE:
      print("len uv=", len(vertices))
    for f in faces[g]:
      iStart = i
      length = len(f['vertex'])
      for component in 'normal', 'uv':
        if length > len(f[component]):
          LOGGER.error('There were more vertices than %ss: %d > %d',
                       component, length, len(f[component]))
          length = len(f[component])

      for v in range(length):
        g_vertices.append(vertices[f['vertex'][v] - 1])
        g_normals.append(normals[f['normal'][v] - 1])
        if (len(f['uv']) > 0 and len(uvs[f['uv'][v] - 1]) == 2):
          g_tex_coords.append(uvs[f['uv'][v] - 1])
        i += 1
      n = i - iStart - 1
      for t in range(1, n):
        g_indices.append((iStart, iStart + t + 1, iStart + t))

    model.buf.append(Buffer(model, g_vertices, g_tex_coords, g_indices, g_normals))
    n = len(model.buf) - 1
    model.vGroup[g] = n

    model.buf[n].indicesLen = len(model.buf[n].indices)
    model.buf[n].material = (0.0, 0.0, 0.0, 0.0)
    model.buf[n].ttype = GL_TRIANGLES


    #for i in range(len(model.vGroup[g].normals)):
    #  print(model.vGroup[g].normals[i], end='')
    if VERBOSE:
      print()
      print("indices=", len(model.buf[n].indices))
      print("vertices=", len(model.buf[n].vertices))
      print("normals=", len(model.buf[n].normals))
      print("tex_coords=", len(model.buf[n].tex_coords))

  material_lib = parse_mtl(open(os.path.join(filePath, mtllib), 'r'))
  for m in materials:
    if VERBOSE:
      print(m)
    if 'mapDiffuse' in material_lib[m]:
      tfileName = material_lib[m]['mapDiffuse']
      model.buf[model.vGroup[materials[m]]].texFile = tfileName
      model.buf[model.vGroup[materials[m]]].textures = [Texture(os.path.join(filePath, tfileName), False, True)] # load from file
    else:
      model.buf[model.vGroup[materials[m]]].texFile = None
      model.buf[model.vGroup[materials[m]]].textures = []
      if 'colorDiffuse' in material_lib[m]:#TODO don't create this array if texture being used though not exclusive.
      #TODO check this works with appropriate mtl file
        redVal = material_lib[m]['colorDiffuse'][0]
        grnVal = material_lib[m]['colorDiffuse'][1]
        bluVal = material_lib[m]['colorDiffuse'][2]
        model.buf[model.vGroup[materials[m]]].material = (redVal, grnVal, bluVal, 1.0)
        model.buf[model.vGroup[materials[m]]].unib[3:6] = [redVal, grnVal, bluVal]
Ejemplo n.º 2
0
def loadFileOBJ(model, fileName):
    """Loads an obj file with associated mtl file to produce Buffer object
  as part of a Shape. Arguments:
    *model*
      Model object to add to.
    *fileName*
      Path and name of obj file relative to program file.
  """
    model.coordinateSystem = "Y-up"
    model.parent = None
    #model.childModel = [] # don't really need parent and child pointers but will speed up traversing tree
    model.vNormal = False
    model.vGroup = {}  # holds the information for each vertex group

    # read in the file and parse into some arrays, name='teapot', z=4

    #import os
    if fileName[0] != '/':
        for p in sys.path:
            if os.path.isfile(
                    p + '/' + fileName
            ):  # this could theoretically get different files with same name
                fileName = p + '/' + fileName
                break
    filePath = os.path.split(os.path.abspath(fileName))[0]
    LOGGER.info(filePath)
    f = open(fileName, 'r')

    vertices = []
    normals = []
    uvs = []

    faces = {}

    materials = {}
    material = ""
    mcounter = 0
    mcurrent = 0
    numv = [
    ]  #number of vertices for each material (nb each vertex will have three coords)
    numi = []  #number of indices (triangle corners) for each material

    mtllib = ""

    # current face state
    group = 0
    objct = 0
    smooth = 0

    for l in f:
        chunks = l.split()
        if len(chunks) > 0:

            # Vertices as (x,y,z) coordinates
            # v 0.123 0.234 0.345
            if chunks[0] == "v" and len(chunks) >= 4:
                x = float(chunks[1])
                y = float(chunks[2])
                z = -float(chunks[3])  # z direction away in gl es 2.0 shaders
                vertices.append((x, y, z))

            # Normals in (x, y, z) form; normals might not be unit
            # vn 0.707 0.000 0.707
            if chunks[0] == "vn" and len(chunks) >= 4:
                x = float(chunks[1])
                y = float(chunks[2])
                z = -float(chunks[3])  # z direction away in gl es 2.0 shaders
                normals.append((x, y, z))

            # Texture coordinates in (u,v)
            # vt 0.500 -1.352
            if chunks[0] == "vt" and len(chunks) >= 3:
                u = float(chunks[1])
                v = float(chunks[2])
                uvs.append((u, v))

            # Face
            if chunks[0] == "f" and len(chunks) >= 4:
                vertex_index = []
                uv_index = []
                normal_index = []

                # Precompute vert / normal / uv lists
                # for negative index lookup
                vertlen = len(vertices) + 1
                normlen = len(normals) + 1
                uvlen = len(uvs) + 1

                if len(numv) < (mcurrent + 1): numv.append(0)
                if len(numi) < (mcurrent + 1): numi.append(0)

                for v in chunks[1:]:
                    numv[mcurrent] += 1
                    numi[mcurrent] += 3
                    vertex = parse_vertex(v)
                    if vertex['v']:
                        if vertex['v'] < 0:
                            vertex['v'] += vertlen
                        vertex_index.append(vertex['v'])
                    if vertex['t']:
                        if vertex['t'] < 0:
                            vertex['t'] += uvlen
                        uv_index.append(vertex['t'])
                    if vertex['n']:
                        if vertex['n'] < 0:
                            vertex['n'] += normlen
                        normal_index.append(vertex['n'])
                numi[
                    mcurrent] -= 6  # number of corners of triangle = (n-2)*3 where n is the number of corners of face
                if not mcurrent in faces: faces[mcurrent] = []

                faces[mcurrent].append({
                    'vertex': vertex_index,
                    'uv': uv_index,
                    'normal': normal_index,
                    'group': group,
                    'object': objct,
                    'smooth': smooth,
                })

            # Group
            if chunks[0] == "g" and len(chunks) == 2:
                group = chunks[1]

            # Object
            if chunks[0] == "o" and len(chunks) == 2:
                objct = chunks[1]

            # Materials definition
            if chunks[0] == "mtllib" and len(chunks) == 2:
                mtllib = chunks[1]

            # Material
            if chunks[0] == "usemtl":
                if len(chunks) > 1:
                    material = chunks[1]
                else:
                    material = ""
                if not material in materials:
                    mcurrent = mcounter
                    materials[material] = mcounter
                    mcounter += 1
                else:
                    mcurrent = materials[material]

            # Smooth shading
            if chunks[0] == "s" and len(chunks) == 2:
                smooth = chunks[1]

    LOGGER.info("materials:  %s\nnumv:  %s", materials, numv)

    for g in faces:
        numv[g] -= 1
        numi[g] -= 1

        g_vertices = []
        g_normals = []
        g_tex_coords = []
        g_indices = []
        i = 0  # vertex counter in this material
        LOGGER.info("len uv=", len(vertices))
        for f in faces[g]:
            iStart = i
            length = len(f['vertex'])
            length_n = len(f['normal'])
            #for component in 'normal', 'uv':
            #  if length > len(f[component]):
            #    LOGGER.error('There were more vertices than %ss: %d > %d',
            #                 component, length, len(f[component]))
            #    length = len(f[component])

            for v in range(length):
                g_vertices.append(vertices[f['vertex'][v] - 1])
                if length_n == length:  #only use normals if there is one for each vertex
                    g_normals.append(normals[f['normal'][v] - 1])
                if (len(f['uv']) > 0 and len(uvs[f['uv'][v] - 1]) == 2):
                    g_tex_coords.append(uvs[f['uv'][v] - 1])
                i += 1
            n = i - iStart - 1
            for t in range(1, n):
                g_indices.append((iStart, iStart + t + 1, iStart + t))
        if len(g_normals) != len(g_vertices):
            g_normals = None  # force Buffer.__init__() to generate normals
        model.buf.append(
            Buffer(model, g_vertices, g_tex_coords, g_indices, g_normals))
        n = len(model.buf) - 1
        model.vGroup[g] = n

        model.buf[n].indicesLen = len(model.buf[n].element_array_buffer)
        model.buf[n].material = (0.0, 0.0, 0.0, 0.0)
        model.buf[n].ttype = GL_TRIANGLES

        LOGGER.info("indices=%s\nvertices=%s",
                    len(model.buf[n].element_array_buffer),
                    len(model.buf[n].array_buffer))

    try:
        material_lib = parse_mtl(open(os.path.join(filePath, mtllib), 'r'))
        for m in materials:
            LOGGER.info(m)
            if 'mapDiffuse' in material_lib[m]:
                tfileName = material_lib[m]['mapDiffuse']
                model.buf[model.vGroup[materials[m]]].texFile = tfileName
                model.buf[model.vGroup[materials[m]]].textures = [
                    Texture(filePath + '/' + tfileName, blend=False, flip=True)
                ]  # load from file
            else:
                model.buf[model.vGroup[materials[m]]].texFile = None
                model.buf[model.vGroup[materials[m]]].textures = []
                if 'colorDiffuse' in material_lib[
                        m]:  #TODO don't create this array if texture being used though not exclusive.
                    #TODO check this works with appropriate mtl file
                    redVal = material_lib[m]['colorDiffuse'][0]
                    grnVal = material_lib[m]['colorDiffuse'][1]
                    bluVal = material_lib[m]['colorDiffuse'][2]
                    model.buf[model.vGroup[materials[m]]].material = (redVal,
                                                                      grnVal,
                                                                      bluVal,
                                                                      1.0)
                    model.buf[model.vGroup[materials[m]]].unib[3:6] = [
                        redVal, grnVal, bluVal
                    ]
    except:
        LOGGER.warning('no material specified')
Ejemplo n.º 3
0
def loadFileOBJ(model, fileName):
  """Loads an obj file with associated mtl file to produce Buffer object
  as part of a Shape. Arguments:
    *model*
      Model object to add to.
    *fileName*
      Path and name of obj file relative to program file.
  """
  model.coordinateSystem = "Y-up"
  model.parent = None
  #model.childModel = [] # don't really need parent and child pointers but will speed up traversing tree
  model.vNormal = False
  model.vGroup = {} # holds the information for each vertex group

  # read in the file and parse into some arrays, name='teapot', z=4

  #import os
  if fileName[0] != '/':
    for p in sys.path:
      if os.path.isfile(p + '/' + fileName): # this could theoretically get different files with same name
        fileName = p + '/' + fileName
        break
  filePath = os.path.split(os.path.abspath(fileName))[0]
  LOGGER.info(filePath)
  f = open(fileName, 'r')

  vertices = []
  normals = []
  uvs = []

  faces = {}

  materials = {}
  material = ""
  mcounter = 0
  mcurrent = 0
  mtllib = ""

  # current face state
  group = 0
  objct = 0
  smooth = 0

  for l in f:
    chunks = l.split()
    if len(chunks) > 0:

      # Vertices as (x,y,z) coordinates
      # v 0.123 0.234 0.345
      if chunks[0] == "v" and len(chunks) >= 4:
        x = float(chunks[1])
        y = float(chunks[2])
        z = -float(chunks[3]) # z direction away in gl es 2.0 shaders
        vertices.append((x, y, z))

      # Normals in (x, y, z) form; normals might not be unit
      # vn 0.707 0.000 0.707
      if chunks[0] == "vn" and len(chunks) >= 4:
        x = float(chunks[1])
        y = float(chunks[2])
        z = -float(chunks[3]) # z direction away in gl es 2.0 shaders
        normals.append((x, y, z))

      # Texture coordinates in (u,v)
      # vt 0.500 -1.352
      if chunks[0] == "vt" and len(chunks) >= 3:
        u = float(chunks[1])
        v = float(chunks[2])
        uvs.append((u, v))

      # Face
      if chunks[0] == "f" and len(chunks) >= 4:
        vertex_index = []
        uv_index = []
        normal_index = []


        # Precompute vert / normal / uv lists
        # for negative index lookup
        vertlen = len(vertices) + 1
        normlen = len(normals) + 1
        uvlen = len(uvs) + 1

        for v in chunks[1:]:
          vertex = parse_vertex(v)
          if vertex['v']:
            if vertex['v'] < 0:
              vertex['v'] += vertlen
            vertex_index.append(vertex['v'])
          if vertex['t']:
            if vertex['t'] < 0:
              vertex['t'] += uvlen
            uv_index.append(vertex['t'])
          if vertex['n']:
            if vertex['n'] < 0:
              vertex['n'] += normlen
            normal_index.append(vertex['n'])
        if not mcurrent in faces:
          faces[mcurrent] = []

        faces[mcurrent].append({
          'vertex':vertex_index,
          'uv':uv_index,
          'normal':normal_index,

          'group':group,
          'object':objct,
          'smooth':smooth,
          })

      # Group
      if chunks[0] == "g" and len(chunks) == 2:
        group = chunks[1]

      # Object
      if chunks[0] == "o" and len(chunks) == 2:
        objct = chunks[1]

      # Materials definition
      if chunks[0] == "mtllib" and len(chunks) == 2:
        mtllib = chunks[1]

      # Material
      if chunks[0] == "usemtl":
        if len(chunks) > 1:
          material = chunks[1]
        else:
          material = ""
        if not material in materials:
          mcurrent = mcounter
          materials[material] = mcounter
          mcounter += 1
        else:
          mcurrent = materials[material]

      # Smooth shading
      if chunks[0] == "s" and len(chunks) == 2:
        smooth = chunks[1]
    
  for g in faces: # make each of these into an array_buffer with its own material
    g_vertices = []
    g_normals = []
    g_tex_coords = []
    g_indices = []
    i = 0 # vertex counter in this material
    LOGGER.info("len uv={}".format(len(vertices)))
    vec_dict = {} # hold unique combinations of v/u/n
    for f in faces[g]:
      vec_list = [] # hold index vals for each array_buffer entry for this face
      length = len(f['vertex'])
      length_n = len(f['normal'])
      length_uv = len(f['uv'])
      for v in range(length):
        vec_tuple = (f['vertex'][v],
                    f['uv'][v] if length_uv > 0 else -1,
                    f['normal'][v] if length_n == length else -1)
        if vec_tuple in vec_dict: #already exists don't duplicate
          vec_list.append(vec_dict[vec_tuple])
        else:
          g_vertices.append(vertices[vec_tuple[0] - 1])
          if length_n == length: #only use normals if there is one for each vertex
            g_normals.append(normals[vec_tuple[2] - 1])
          if (length_uv > 0 and len(uvs[vec_tuple[1] - 1]) == 2):
            g_tex_coords.append(uvs[vec_tuple[1] - 1])
          vec_dict[vec_tuple] = i
          vec_list.append(i)
          i += 1
      for t in range(len(vec_list) - 2):
        g_indices.append((vec_list[0], vec_list[t + 2], vec_list[t + 1]))
    if len(g_normals) != len(g_vertices):
      g_normals = None # force Buffer.__init__() to generate normals
    model.buf.append(Buffer(model, g_vertices, g_tex_coords, g_indices, g_normals))
    n = len(model.buf) - 1
    model.vGroup[g] = n

    model.buf[n].indicesLen = len(model.buf[n].element_array_buffer)
    model.buf[n].material = (0.0, 0.0, 0.0, 0.0)
    model.buf[n].draw_method = GL_TRIANGLES

    LOGGER.info("indices=%s\nvertices=%s", len(model.buf[n].element_array_buffer), 
                                       len(model.buf[n].array_buffer))

  try:
    material_lib = parse_mtl(open(os.path.join(filePath, mtllib), 'r'))
    for m in materials:
      LOGGER.info(m)
      if 'mapDiffuse' in material_lib[m]:
        tfileName = material_lib[m]['mapDiffuse']
        model.buf[model.vGroup[materials[m]]].texFile = tfileName
        model.buf[model.vGroup[materials[m]]].textures = [Texture(filePath + '/' + tfileName, blend=False, flip=True)] # load from file
      else:
        model.buf[model.vGroup[materials[m]]].texFile = None
        model.buf[model.vGroup[materials[m]]].textures = []
        if 'colorDiffuse' in material_lib[m]:#TODO don't create this array if texture being used though not exclusive.
        #TODO check this works with appropriate mtl file
          redVal = material_lib[m]['colorDiffuse'][0]
          grnVal = material_lib[m]['colorDiffuse'][1]
          bluVal = material_lib[m]['colorDiffuse'][2]
          model.buf[model.vGroup[materials[m]]].material = (redVal, grnVal, bluVal, 1.0)
          model.buf[model.vGroup[materials[m]]].unib[3:6] = [redVal, grnVal, bluVal]
  except:
    LOGGER.warning('no material specified')
Ejemplo n.º 4
0
def loadFileOBJ(model,fileName,texs):

  model.coordinateSystem = "Y-up"
  model.parent = None
  model.childModel = [] # don't really need parent and child pointers but will speed up traversing tree
  model.vNormal = False
  model.vGroup = {} # holds the information for each vertex group
  model.texs = texs

  if ("__clone__" in fileName): return #used for cloning this loadModel, i.e. don't need to parse egg file
  # read in the file and parse into some arrays

  filePath = os.path.split(os.path.abspath(fileName))[0]
  print filePath
  f = open(fileName, 'r')

  vertices = []
  normals = []
  uvs = []

  faces = {}

  materials = {}
  material = ""
  mcounter = 0
  mcurrent = 0
  numv = [] #number of vertices for each material (nb each vertex will have three coords)
  numi = [] #number of indices (triangle corners) for each material

  mtllib = ""

  # current face state
  group = 0
  object = 0
  smooth = 0

  for l in f:
    chunks = l.split()
    if len(chunks) > 0:

      # Vertices as (x,y,z) coordinates
      # v 0.123 0.234 0.345
      if chunks[0] == "v" and len(chunks) == 4:
        x = float(chunks[1])
        y = float(chunks[2])
        z = float(chunks[3])
        vertices.append([x,y,z])

      # Normals in (x,y,z) form; normals might not be unit
      # vn 0.707 0.000 0.707
      if chunks[0] == "vn" and len(chunks) == 4:
        x = float(chunks[1])
        y = float(chunks[2])
        z = float(chunks[3])
        normals.append([x,y,z])

      # Texture coordinates in (u,v)
      # vt 0.500 -1.352
      if chunks[0] == "vt" and len(chunks) >= 3:
        u = float(chunks[1])
        v = float(chunks[2])
        uvs.append([u,v])

      # Face
      if chunks[0] == "f" and len(chunks) >= 4:
        vertex_index = []
        uv_index = []
        normal_index = []


        # Precompute vert / normal / uv lists
        # for negative index lookup
        vertlen = len(vertices) + 1
        normlen = len(normals) + 1
        uvlen = len(uvs) + 1

        if len(numv) < (mcurrent+1): numv.append(0)
        if len(numi) < (mcurrent+1): numi.append(0)

        for v in chunks[1:]:
          numv[mcurrent] += 1
          numi[mcurrent] += 3
          vertex = parse_vertex(v)
          if vertex['v']:
            if vertex['v'] < 0:
              vertex['v'] += vertlen
            vertex_index.append(vertex['v'])
          if vertex['t']:
            if vertex['t'] < 0:
              vertex['t'] += uvlen
            uv_index.append(vertex['t'])
          if vertex['n']:
            if vertex['n'] < 0:
              vertex['n'] += normlen
            normal_index.append(vertex['n'])
        numi[mcurrent] -= 6 # number of corners of triangle = (n-2)*3 where n is the number of corners of face
        if not mcurrent in faces: faces[mcurrent] = []

        faces[mcurrent].append({
          'vertex':vertex_index,
          'uv':uv_index,
          'normal':normal_index,

          'group':group,
          'object':object,
          'smooth':smooth,
          })

      # Group
      if chunks[0] == "g" and len(chunks) == 2:
        group = chunks[1]

      # Object
      if chunks[0] == "o" and len(chunks) == 2:
        object = chunks[1]

      # Materials definition
      if chunks[0] == "mtllib" and len(chunks) == 2:
        mtllib = chunks[1]

      # Material
      if chunks[0] == "usemtl":
        if len(chunks) > 1:
          material = chunks[1]
        else:
          material = ""
        if not material in materials:
          mcurrent = mcounter
          materials[material] = mcounter
          mcounter += 1
        else:
          mcurrent = materials[material]

      # Smooth shading
      if chunks[0] == "s" and len(chunks) == 2:
        smooth = chunks[1]

  print "materials:  ", materials
  print "numv: ", numv

  for g in faces:
    numv[g] -= 1
    numi[g] -= 1
    model.vGroup[g] = Shape("", model.x, model.y, model.z, model.rotx,model.roty,model.rotz, model.sx,model.sy,model.sz, model.cx,model.cy,model.cz)
    ctype_array1 = c_float*(numv[g] * 3 + 3)
    model.vGroup[g].vertices = ctype_array1()
    model.vGroup[g].normals = ctype_array1()
    ctype_array2 = c_float*(numv[g] * 2 + 2)
    model.vGroup[g].tex_coords = ctype_array2()
    ctype_array3 = c_short*(numi[g] + 1)
    model.vGroup[g].indices = ctype_array3()
    i = 0 # vertex counter in this material
    j = 0 # triangle vertex count in this material
    print "len uv=",len(vertices)
    for f in faces[g]:
      iStart = i
      for v in range(len(f['vertex'])):
        for k in range(0,3):
          model.vGroup[g].vertices[i*3+k] = c_float(vertices[f['vertex'][v]-1][k])
          model.vGroup[g].normals[i*3+k] = c_float(normals[f['normal'][v]-1][k])
        if (len(f['uv']) > 0 and len(uvs[f['uv'][v]-1]) == 2):
          for k in range(0,2):
            model.vGroup[g].tex_coords[i*2+k] = c_float(uvs[f['uv'][v]-1][k])
        i += 1
      n = i - iStart - 1
      for t in range(1,n):
        model.vGroup[g].indices[j*3] = c_short(iStart)
        model.vGroup[g].indices[j*3+1] = c_short(iStart + t)
        model.vGroup[g].indices[j*3+2] = c_short(iStart + t +1)
        j += 1
    model.vGroup[g].indicesLen = len(model.vGroup[g].indices)
    model.vGroup[g].material = None
    model.vGroup[g].ttype = GL_TRIANGLES


    #for i in range(len(model.vGroup[g].normals)):
    #  print model.vGroup[g].normals[i],
    print
    print "indices=",len(model.vGroup[g].indices)
    print "vertices=",len(model.vGroup[g].vertices)
    print "normals=",len(model.vGroup[g].normals)
    print "tex_coords=",len(model.vGroup[g].tex_coords)

  material_lib = parse_mtl(open(os.path.join(filePath, mtllib), 'r'))
  for m in materials:
    print m
    if 'mapDiffuse' in material_lib[m]:
      tfileName = material_lib[m]['mapDiffuse']
      model.vGroup[materials[m]].texFile = tfileName
      model.vGroup[materials[m]].texID = model.texs.loadTexture(os.path.join(filePath, tfileName), False, True) # load from file
    else:
      model.vGroup[materials[m]].texFile = None
      model.vGroup[materials[m]].texID = None
    if 'colorDiffuse' in material_lib[m]:#TODO maybe don't create this array if texture being used though not exclusive.
    #TODO used by pi3d if light set
      ctype_array4 = c_byte*((numi[materials[m]] + 1)*4)
      model.vGroup[materials[m]].material = ctype_array4()
      redVal = int(material_lib[m]['colorDiffuse'][0] * 255.0)
      grnVal = int(material_lib[m]['colorDiffuse'][1] * 255.0)
      bluVal = int(material_lib[m]['colorDiffuse'][2] * 255.0)
      for i in xrange(0, (numi[materials[m]] + 1)*4, 4):
        model.vGroup[materials[m]].material[i] = c_byte(redVal)
        model.vGroup[materials[m]].material[i + 1] = c_byte(grnVal)
        model.vGroup[materials[m]].material[i + 2] = c_byte(bluVal)
        model.vGroup[materials[m]].material[i + 3] = c_byte(255)
 def test_cow(self):
   self.assertEqual(COW_RESULT, parse_mtl(COW_MTL.splitlines()))
 def test_teapot(self):
   self.assertEqual(TEAPOT_RESULT, parse_mtl(TEAPOT_MTL.splitlines()))
Ejemplo n.º 7
0
def loadFileOBJ(model, fileName):
  """Loads an obj file with associated mtl file to produce Buffer object
  as part of a Shape. Arguments:
    *model*
      Model object to add to.
    *fileName*
      Path and name of obj file relative to program file.
  """
  model.coordinateSystem = "Y-up"
  model.parent = None
  #model.childModel = [] # don't really need parent and child pointers but will speed up traversing tree
  model.vNormal = False
  model.vGroup = {} # holds the information for each vertex group

  # read in the file and parse into some arrays, name='teapot', z=4

  #import os
  if fileName[0] != '/':
    for p in sys.path:
      if os.path.isfile(p + '/' + fileName): # this could theoretically get different files with same name
        fileName = p + '/' + fileName
        break
  filePath = os.path.split(os.path.abspath(fileName))[0]
  LOGGER.debug(filePath)
  f = open(fileName, 'r')

  vertices = []
  normals = []
  uvs = []

  faces = {}

  materials = {}
  material = ""
  mcounter = 0
  mcurrent = 0
  mtllib = ""

  # current face state
  group = 0
  objct = 0
  smooth = 0

  for l in f:
    chunks = l.split()
    if len(chunks) > 0:

      # Vertices as (x,y,z) coordinates
      # v 0.123 0.234 0.345
      if chunks[0] == "v" and len(chunks) >= 4:
        x = float(chunks[1])
        y = float(chunks[2])
        z = -float(chunks[3]) # z direction away in gl es 2.0 shaders
        vertices.append((x, y, z))

      # Normals in (x, y, z) form; normals might not be unit
      # vn 0.707 0.000 0.707
      if chunks[0] == "vn" and len(chunks) >= 4:
        x = float(chunks[1])
        y = float(chunks[2])
        z = -float(chunks[3]) # z direction away in gl es 2.0 shaders
        normals.append((x, y, z))

      # Texture coordinates in (u,v)
      # vt 0.500 -1.352
      if chunks[0] == "vt" and len(chunks) >= 3:
        u = float(chunks[1])
        v = float(chunks[2])
        uvs.append((u, v))

      # Face
      if chunks[0] == "f" and len(chunks) >= 4:
        vertex_index = []
        uv_index = []
        normal_index = []


        # Precompute vert / normal / uv lists
        # for negative index lookup
        vertlen = len(vertices) + 1
        normlen = len(normals) + 1
        uvlen = len(uvs) + 1

        for v in chunks[1:]:
          vertex = parse_vertex(v)
          if vertex['v']:
            if vertex['v'] < 0:
              vertex['v'] += vertlen
            vertex_index.append(vertex['v'])
          if vertex['t']:
            if vertex['t'] < 0:
              vertex['t'] += uvlen
            uv_index.append(vertex['t'])
          if vertex['n']:
            if vertex['n'] < 0:
              vertex['n'] += normlen
            normal_index.append(vertex['n'])
        if not mcurrent in faces:
          faces[mcurrent] = []

        faces[mcurrent].append({
          'vertex':vertex_index,
          'uv':uv_index,
          'normal':normal_index,

          'group':group,
          'object':objct,
          'smooth':smooth,
          })

      # Group
      if chunks[0] == "g" and len(chunks) == 2:
        group = chunks[1]

      # Object
      if chunks[0] == "o" and len(chunks) == 2:
        objct = chunks[1]

      # Materials definition
      if chunks[0] == "mtllib" and len(chunks) == 2:
        mtllib = chunks[1]

      # Material
      if chunks[0] == "usemtl":
        if len(chunks) > 1:
          material = chunks[1]
        else:
          material = ""
        if not material in materials:
          mcurrent = mcounter
          materials[material] = mcounter
          mcounter += 1
        else:
          mcurrent = materials[material]

      # Smooth shading
      if chunks[0] == "s" and len(chunks) == 2:
        smooth = chunks[1]
    
  for g in faces: # make each of these into an array_buffer with its own material
    g_vertices = []
    g_normals = []
    g_tex_coords = []
    g_indices = []
    i = 0 # vertex counter in this material
    LOGGER.debug("len uv={}".format(len(vertices)))
    vec_dict = {} # hold unique combinations of v/u/n
    for f in faces[g]:
      vec_list = [] # hold index vals for each array_buffer entry for this face
      length = len(f['vertex'])
      length_n = len(f['normal'])
      length_uv = len(f['uv'])
      for v in range(length):
        vec_tuple = (f['vertex'][v],
                    f['uv'][v] if length_uv > 0 else -1,
                    f['normal'][v] if length_n == length else -1)
        if vec_tuple in vec_dict: #already exists don't duplicate
          vec_list.append(vec_dict[vec_tuple])
        else:
          g_vertices.append(vertices[vec_tuple[0] - 1])
          if length_n == length: #only use normals if there is one for each vertex
            g_normals.append(normals[vec_tuple[2] - 1])
          if (length_uv > 0 and len(uvs[vec_tuple[1] - 1]) == 2):
            g_tex_coords.append(uvs[vec_tuple[1] - 1])
          vec_dict[vec_tuple] = i
          vec_list.append(i)
          i += 1
      for t in range(len(vec_list) - 2):
        g_indices.append((vec_list[0], vec_list[t + 2], vec_list[t + 1]))
    if len(g_normals) != len(g_vertices):
      g_normals = None # force Buffer.__init__() to generate normals
    model.buf.append(Buffer(model, g_vertices, g_tex_coords, g_indices, g_normals))
    n = len(model.buf) - 1
    model.vGroup[g] = n

    model.buf[n].indicesLen = len(model.buf[n].element_array_buffer)
    model.buf[n].material = (0.0, 0.0, 0.0, 0.0)
    model.buf[n].draw_method = GL_TRIANGLES

    LOGGER.debug("indices=%s\nvertices=%s", len(model.buf[n].element_array_buffer), 
                                       len(model.buf[n].array_buffer))

  try:
    material_lib = parse_mtl(open(os.path.join(filePath, mtllib), 'r'))
    for m in materials:
      LOGGER.debug(m)
      if 'mapDiffuse' in material_lib[m]:
        tfileName = material_lib[m]['mapDiffuse']
        model.buf[model.vGroup[materials[m]]].texFile = tfileName
        model.buf[model.vGroup[materials[m]]].textures = [Texture(filePath + '/' + tfileName, blend=False, flip=True)] # load from file
      else:
        model.buf[model.vGroup[materials[m]]].texFile = None
        model.buf[model.vGroup[materials[m]]].textures = []
        if 'colorDiffuse' in material_lib[m]:#TODO don't create this array if texture being used though not exclusive.
        #TODO check this works with appropriate mtl file
          redVal = material_lib[m]['colorDiffuse'][0]
          grnVal = material_lib[m]['colorDiffuse'][1]
          bluVal = material_lib[m]['colorDiffuse'][2]
          model.buf[model.vGroup[materials[m]]].material = (redVal, grnVal, bluVal, 1.0)
          model.buf[model.vGroup[materials[m]]].unib[3:6] = [redVal, grnVal, bluVal]
  except:
    LOGGER.warning('no material specified')
Ejemplo n.º 8
0
def loadFileOBJ(model, fileName):
    """Loads an obj file with associated mtl file to produce Buffer object
  as part of a Shape. Arguments:
    *model*
      Model object to add to.
    *fileName*
      Path and name of obj file relative to top directory.
  """
    model.coordinateSystem = "Y-up"
    model.parent = None
    model.childModel = [
    ]  # don't really need parent and child pointers but will speed up traversing tree
    model.vNormal = False
    model.vGroup = {}  # holds the information for each vertex group

    # read in the file and parse into some arrays

    filePath = os.path.split(os.path.abspath(fileName))[0]
    print filePath
    f = open(fileName, 'r')

    vertices = []
    normals = []
    uvs = []

    faces = {}

    materials = {}
    material = ""
    mcounter = 0
    mcurrent = 0
    numv = [
    ]  #number of vertices for each material (nb each vertex will have three coords)
    numi = []  #number of indices (triangle corners) for each material

    mtllib = ""

    # current face state
    group = 0
    objct = 0
    smooth = 0

    for l in f:
        chunks = l.split()
        if len(chunks) > 0:

            # Vertices as (x,y,z) coordinates
            # v 0.123 0.234 0.345
            if chunks[0] == "v" and len(chunks) == 4:
                x = float(chunks[1])
                y = float(chunks[2])
                z = -float(chunks[3])  # z direction away in gl es 2.0 shaders
                vertices.append((x, y, z))

            # Normals in (x, y, z) form; normals might not be unit
            # vn 0.707 0.000 0.707
            if chunks[0] == "vn" and len(chunks) == 4:
                x = float(chunks[1])
                y = float(chunks[2])
                z = -float(chunks[3])  # z direction away in gl es 2.0 shaders
                normals.append((x, y, z))

            # Texture coordinates in (u,v)
            # vt 0.500 -1.352
            if chunks[0] == "vt" and len(chunks) >= 3:
                u = float(chunks[1])
                v = float(chunks[2])
                uvs.append((u, v))

            # Face
            if chunks[0] == "f" and len(chunks) >= 4:
                vertex_index = []
                uv_index = []
                normal_index = []

                # Precompute vert / normal / uv lists
                # for negative index lookup
                vertlen = len(vertices) + 1
                normlen = len(normals) + 1
                uvlen = len(uvs) + 1

                if len(numv) < (mcurrent + 1): numv.append(0)
                if len(numi) < (mcurrent + 1): numi.append(0)

                for v in chunks[1:]:
                    numv[mcurrent] += 1
                    numi[mcurrent] += 3
                    vertex = parse_vertex(v)
                    if vertex['v']:
                        if vertex['v'] < 0:
                            vertex['v'] += vertlen
                        vertex_index.append(vertex['v'])
                    if vertex['t']:
                        if vertex['t'] < 0:
                            vertex['t'] += uvlen
                        uv_index.append(vertex['t'])
                    if vertex['n']:
                        if vertex['n'] < 0:
                            vertex['n'] += normlen
                        normal_index.append(vertex['n'])
                numi[
                    mcurrent] -= 6  # number of corners of triangle = (n-2)*3 where n is the number of corners of face
                if not mcurrent in faces: faces[mcurrent] = []

                faces[mcurrent].append({
                    'vertex': vertex_index,
                    'uv': uv_index,
                    'normal': normal_index,
                    'group': group,
                    'object': objct,
                    'smooth': smooth,
                })

            # Group
            if chunks[0] == "g" and len(chunks) == 2:
                group = chunks[1]

            # Object
            if chunks[0] == "o" and len(chunks) == 2:
                objct = chunks[1]

            # Materials definition
            if chunks[0] == "mtllib" and len(chunks) == 2:
                mtllib = chunks[1]

            # Material
            if chunks[0] == "usemtl":
                if len(chunks) > 1:
                    material = chunks[1]
                else:
                    material = ""
                if not material in materials:
                    mcurrent = mcounter
                    materials[material] = mcounter
                    mcounter += 1
                else:
                    mcurrent = materials[material]

            # Smooth shading
            if chunks[0] == "s" and len(chunks) == 2:
                smooth = chunks[1]
    if VERBOSE:
        print "materials:  ", materials
        print "numv: ", numv

    for g in faces:
        numv[g] -= 1
        numi[g] -= 1

        g_vertices = []
        g_normals = []
        g_tex_coords = []
        g_indices = []
        i = 0  # vertex counter in this material
        if VERBOSE:
            print "len uv=", len(vertices)
        for f in faces[g]:
            iStart = i
            for v in range(len(f['vertex'])):
                g_vertices.append(vertices[f['vertex'][v] - 1])
                g_normals.append(normals[f['normal'][v] - 1])
                if (len(f['uv']) > 0 and len(uvs[f['uv'][v] - 1]) == 2):
                    g_tex_coords.append(uvs[f['uv'][v] - 1])
                i += 1
            n = i - iStart - 1
            for t in range(1, n):
                g_indices.append((iStart, iStart + t + 1, iStart + t))

        model.buf.append(
            Buffer(model, g_vertices, g_tex_coords, g_indices, g_normals))
        n = len(model.buf) - 1
        model.vGroup[g] = n

        model.buf[n].indicesLen = len(model.buf[n].indices)
        model.buf[n].material = (0.0, 0.0, 0.0, 0.0)
        model.buf[n].ttype = GL_TRIANGLES

        #for i in range(len(model.vGroup[g].normals)):
        #  print model.vGroup[g].normals[i],
        if VERBOSE:
            print
            print "indices=", len(model.buf[n].indices)
            print "vertices=", len(model.buf[n].vertices)
            print "normals=", len(model.buf[n].normals)
            print "tex_coords=", len(model.buf[n].tex_coords)

    material_lib = parse_mtl(open(os.path.join(filePath, mtllib), 'r'))
    for m in materials:
        if VERBOSE:
            print m
        if 'mapDiffuse' in material_lib[m]:
            tfileName = material_lib[m]['mapDiffuse']
            model.buf[model.vGroup[materials[m]]].texFile = tfileName
            model.buf[model.vGroup[materials[m]]].textures = [
                Texture(os.path.join(filePath, tfileName), False, True)
            ]  # load from file
        else:
            model.buf[model.vGroup[materials[m]]].texFile = None
            model.buf[model.vGroup[materials[m]]].textures = []
            if 'colorDiffuse' in material_lib[
                    m]:  #TODO don't create this array if texture being used though not exclusive.
                #TODO check this works with appropriate mtl file
                redVal = material_lib[m]['colorDiffuse'][0]
                grnVal = material_lib[m]['colorDiffuse'][1]
                bluVal = material_lib[m]['colorDiffuse'][2]
                model.buf[model.vGroup[materials[m]]].material = (redVal,
                                                                  grnVal,
                                                                  bluVal, 1.0)
                model.buf[model.vGroup[materials[m]]].unib[3:6] = [
                    redVal, grnVal, bluVal
                ]