Example #1
0
    def __init__(self, shape, pts, texcoords, faces, normals=None, smooth=True):
        """Generate a vertex buffer to hold data and indices. If no normals
    are provided then these are generated.

    Arguments:
      *shape*
        Shape object that this Buffer is a child of
      *pts*
        array of vertices tuples i.e. [(x0,y0,z0), (x1,y1,z1),...]
      *texcoords*
        array of texture (uv) coordinates tuples
        i.e. [(u0,v0), (u1,v1),...]
      *faces*
        array of indices (of pts array) defining triangles
        i.e. [(a0,b0,c0), (a1,b1,c1),...]

    Keyword arguments:
      *normals*
        array of vector component tuples defining normals at each
        vertex i.e. [(x0,y0,z0), (x1,y1,z1),...]
      *smooth*
        if calculating normals then average normals for all faces
        meeting at this vertex, otherwise just use first (for speed).

    """
        super(Buffer, self).__init__()

        # Uniform variables all in one array!
        self.unib = (c_float * 9)(0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 1.0, 1.0, 0.0)
        """ pass to shader array of vec3 uniform variables:

    ===== ============================ ==== ==
    vec3        description            python
    ----- ---------------------------- -------
    index                              from to
    ===== ============================ ==== ==
        0  ntile, shiny, blend           0   2
        1  material                      3   5
        2  umult, vmult (only 2 used)    6   7
    ===== ============================ ==== ==
    """
        self.shape = shape

        if not normals:
            LOGGER.debug("Calculating normals ...")

            normals = [[] for p in pts]
            # Calculate normals.
            for f in faces:
                a, b, c = f[0:3]

                ab = Utility.vec_sub(pts[a], pts[b])
                bc = Utility.vec_sub(pts[a], pts[c])
                n = tuple(Utility.vec_normal(Utility.vec_cross(ab, bc)))
                for x in f[0:3]:
                    normals[x].append(n)

            for i, n in enumerate(normals):
                if n:
                    if smooth:
                        norms = [sum(v[k] for v in n) for k in range(3)]
                    else:  # This should be slightly faster for large shapes
                        norms = [n[0][k] for k in range(3)]
                    normals[i] = tuple(Utility.vec_normal(norms))
                else:
                    normals[i] = 0, 0, 0.01

        # keep a copy for speeding up the collision testing of ElevationMap
        self.vertices = pts
        self.normals = normals
        self.tex_coords = texcoords
        self.indices = faces
        self.material = (0.5, 0.5, 0.5, 1.0)

        # Pack points,normals and texcoords into tuples and convert to ctype floats.
        points = [p + n + t for p, n, t in zip(pts, normals, texcoords)]
        self.array_buffer = c_floats(list(itertools.chain(*points)))

        self.ntris = len(faces)
        points = [f[0:3] for f in faces]
        self.element_array_buffer = c_shorts(list(itertools.chain(*points)))
Example #2
0
    def _lathe(self, path, sides=12, rise=0.0, loops=1.0):
        """Returns a Buffer object by rotating the points defined in path.

    Arguments:
      *path*
        An array of points [(x0, y0), (x1, y1) ...] to rotate around
        the y axis.

    Keyword arguments:
      *sides*
        Number of sides to divide each rotation into.
      *rise*
        Amount to increment the path y values for each rotation (ie helix)
      *loops*
        Number of times to rotate the path by 360 (ie helix).

    """
        self.sides = sides

        s = len(path)
        rl = int(self.sides * loops)

        pn = 0
        pp = 0
        tcx = 1.0 / self.sides
        pr = (pi / self.sides) * 2.0
        rdiv = rise / rl

        # Find largest and smallest y of the path used for stretching the texture
        miny = path[0][1]
        maxy = path[s - 1][1]
        for p in range(s):
            if path[p][1] < miny:
                miny = path[p][1]
            if path[p][1] > maxy:
                maxy = path[p][1]

        verts = []
        norms = []
        idx = []
        tex_coords = []

        opx = path[0][0]
        opy = path[0][1]

        for p in range(s):

            px = path[p][0] * 1.0
            py = path[p][1] * 1.0

            tcy = 1.0 - ((py - miny) / (maxy - miny))

            # Normalized 2D vector between path points
            dx, dy = Utility.vec_normal(Utility.vec_sub((px, py), (opx, opy)))

            for r in range(0, rl):
                sinr = sin(pr * r)
                cosr = cos(pr * r)
                verts.append((px * sinr, py, px * cosr))
                norms.append((-sinr * dy, dx, -cosr * dy))
                tex_coords.append((1.0 - tcx * r, tcy))
                py += rdiv

            # Last path profile (tidies texture coords).
            verts.append((0, py, px))
            norms.append((0, dx, -dy))
            tex_coords.append((0, tcy))

            if p < s - 1:
                pn += (rl + 1)
                for r in range(rl):
                    idx.append((pp + r + 1, pp + r, pn + r))
                    idx.append((pn + r, pn + r + 1, pp + r + 1))
                pp += (rl + 1)

            opx = px
            opy = py

        return Buffer(self, verts, tex_coords, idx, norms)
Example #3
0
File: Shape.py Project: Biniou/pi3d
  def _lathe(self, path, sides=12, rise=0.0, loops=1.0):
    """Returns a Buffer object by rotating the points defined in path.

    Arguments:
      *path*
        An array of points [(x0, y0), (x1, y1) ...] to rotate around
        the y axis.

    Keyword arguments:
      *sides*
        Number of sides to divide each rotation into.
      *rise*
        Amount to increment the path y values for each rotation (ie helix)
      *loops*
        Number of times to rotate the path by 360 (ie helix).

    """
    self.sides = sides

    s = len(path)
    rl = int(self.sides * loops)

    pn = 0
    pp = 0
    tcx = 1.0 / self.sides
    pr = (pi / self.sides) * 2.0
    rdiv = rise / rl

    # Find largest and smallest y of the path used for stretching the texture
    miny = path[0][1]
    maxy = path[s-1][1]
    for p in range(s):
      if path[p][1] < miny:
        miny = path[p][1]
      if path[p][1] > maxy:
        maxy = path[p][1]

    verts = []
    norms = []
    idx = []
    tex_coords = []

    opx = path[0][0]
    opy = path[0][1]

    for p in range(s):

      px = path[p][0] * 1.0
      py = path[p][1] * 1.0

      tcy = 1.0 - ((py - miny) / (maxy - miny))

      # Normalized 2D vector between path points
      dx, dy = Utility.vec_normal(Utility.vec_sub((px, py), (opx, opy)))

      for r in range (0, rl):
        sinr = sin(pr * r)
        cosr = cos(pr * r)
        verts.append((px * sinr, py, px * cosr))
        norms.append((-sinr * dy, dx, -cosr * dy))
        tex_coords.append((1.0 - tcx * r, tcy))
        py += rdiv

      # Last path profile (tidies texture coords).
      verts.append((0, py, px))
      norms.append((0, dx, -dy))
      tex_coords.append((0, tcy))

      if p < s - 1:
        pn += (rl + 1)
        for r in range(rl):
          idx.append((pp + r + 1, pp + r, pn + r))
          idx.append((pn + r, pn + r + 1, pp + r + 1))
        pp += (rl + 1)

      opx = px
      opy = py

    return Buffer(self, verts, tex_coords, idx, norms)
Example #4
0
File: Shape.py Project: John-P/pi3d
  def _lathe(self, path, sides=12, rise=0.0, loops=1.0):
    """Returns a Buffer object by rotating the points defined in path.

    Arguments:
      *path*
        An array of points [(x0, y0), (x1, y1) ...] to rotate around
        the y axis.

    Keyword arguments:
      *sides*
        Number of sides to divide each rotation into.
      *rise*
        Amount to increment the path y values for each rotation (ie helix)
      *loops*
        Number of times to rotate the path by 360 (ie helix).

    """
    self.sides = sides

    s = len(path)
    rl = int(self.sides * loops)

    pn = 0
    pp = 0
    tcx = 1.0 / self.sides
    pr = (pi / self.sides) * 2.0
    rdiv = rise / rl

    # Find length of the path
    path_len = 0.0
    for p in range(1, s):
      path_len += ((path[p][0] - path[p-1][0])**2 +
                   (path[p][1] - path[p-1][1])**2)**0.5

    verts = []
    norms = []
    idx = []
    tex_coords = []

    opx = path[0][0]
    opy = path[0][1]

    tcy = 0.0
    for p in range(s):

      px = path[p][0] * 1.0
      py = path[p][1] * 1.0

      if p > 0:
        tcy += ((path[p][0] - path[p-1][0])**2 +
                (path[p][1] - path[p-1][1])**2)**0.5 / path_len

      # Normalized 2D vector between path points
      if p == 0:
        ipx, ipy = path[1][0] * 1.0, path[1][1] * 1.0
      else:
        ipx, ipy = px, py
      dx, dy = Utility.vec_normal(Utility.vec_sub((ipx, ipy), (opx, opy)))

      for r in range (0, rl + 1):
        sinr = sin(pr * r)
        cosr = cos(pr * r)
        verts.append((px * sinr, py, px * cosr))
        norms.append((-sinr * dy, dx, -cosr * dy))
        tex_coords.append((1.0 - tcx * r, tcy))
        py += rdiv

      if p < s - 1:
        pn += (rl + 1)
        for r in range(rl):
          idx.append((pp + r + 1, pp + r, pn + r))
          idx.append((pn + r, pn + r + 1, pp + r + 1))
        pp += (rl + 1)

      opx = px
      opy = py

    return Buffer(self, verts, tex_coords, idx, norms)
Example #5
0
    def _lathe(self, path, sides=12, rise=0.0, loops=1.0):
        """Returns a Buffer object by rotating the points defined in path.

    Arguments:
      *path*
        An array of points [(x0, y0), (x1, y1) ...] to rotate around
        the y axis.

    Keyword arguments:
      *sides*
        Number of sides to divide each rotation into.
      *rise*
        Amount to increment the path y values for each rotation (ie helix)
      *loops*
        Number of times to rotate the path by 360 (ie helix).

    """
        self.sides = sides

        s = len(path)
        rl = int(self.sides * loops)

        pn = 0
        pp = 0
        tcx = 1.0 / self.sides
        pr = (pi / self.sides) * 2.0
        rdiv = rise / rl

        # Find length of the path
        path_len = 0.0
        for p in range(1, s):
            path_len += ((path[p][0] - path[p - 1][0])**2 +
                         (path[p][1] - path[p - 1][1])**2)**0.5

        verts = []
        norms = []
        idx = []
        tex_coords = []

        opx = path[0][0]
        opy = path[0][1]

        tcy = 0.0
        for p in range(s):

            px = path[p][0] * 1.0
            py = path[p][1] * 1.0

            if p > 0:
                tcy += ((path[p][0] - path[p - 1][0])**2 +
                        (path[p][1] - path[p - 1][1])**2)**0.5 / path_len

            # Normalized 2D vector between path points
            if p == 0:
                ipx, ipy = path[1][0] * 1.0, path[1][1] * 1.0
            else:
                ipx, ipy = px, py
            dx, dy = Utility.vec_normal(Utility.vec_sub((ipx, ipy),
                                                        (opx, opy)))

            for r in range(0, rl + 1):
                sinr = sin(pr * r)
                cosr = cos(pr * r)
                verts.append((px * sinr, py, px * cosr))
                norms.append((-sinr * dy, dx, -cosr * dy))
                tex_coords.append((1.0 - tcx * r, tcy))
                py += rdiv

            if p < s - 1:
                pn += (rl + 1)
                for r in range(rl):
                    idx.append((pp + r + 1, pp + r, pn + r))
                    idx.append((pn + r, pn + r + 1, pp + r + 1))
                pp += (rl + 1)

            opx = px
            opy = py

        return Buffer(self, verts, tex_coords, idx, norms)
Example #6
0
    def __init__(self,
                 shape,
                 pts,
                 texcoords,
                 faces,
                 normals=None,
                 smooth=True):
        """Generate a vertex buffer to hold data and indices. If no normals
    are provided then these are generated.

    Arguments:
      *shape*
        Shape object that this Buffer is a child of
      *pts*
        array of vertices tuples i.e. [(x0,y0,z0), (x1,y1,z1),...]
      *texcoords*
        array of texture (uv) coordinates tuples
        i.e. [(u0,v0), (u1,v1),...]
      *faces*
        array of indices (of pts array) defining triangles
        i.e. [(a0,b0,c0), (a1,b1,c1),...]

    Keyword arguments:
      *normals*
        array of vector component tuples defining normals at each
        vertex i.e. [(x0,y0,z0), (x1,y1,z1),...]
      *smooth*
        if calculating normals then average normals for all faces
        meeting at this vertex, otherwise just use first (for speed).

    """
        super(Buffer, self).__init__()

        # Uniform variables all in one array!
        self.unib = (c_float * 12)(0.0, 0.0, 0.0, 0.5, 0.5, 0.5, 1.0, 1.0, 0.0,
                                   0.0, 0.0, 0.0)
        """ pass to shader array of vec3 uniform variables:

    ===== ============================ ==== ==
    vec3        description            python
    ----- ---------------------------- -------
    index                              from to
    ===== ============================ ==== ==
        0  ntile, shiny, blend           0   2
        1  material                      3   5
        2  umult, vmult (only 2 used)    6   7
        3  u_off, v_off (only 2 used)    9  10
    ===== ============================ ==== ==
    """
        self.shape = shape

        if not normals:
            LOGGER.debug("Calculating normals ...")

            normals = [[] for p in pts]
            # Calculate normals.
            for f in faces:
                a, b, c = f[0:3]

                ab = Utility.vec_sub(pts[a], pts[b])
                bc = Utility.vec_sub(pts[a], pts[c])
                n = tuple(Utility.vec_normal(Utility.vec_cross(ab, bc)))
                for x in f[0:3]:
                    normals[x].append(n)

            for i, n in enumerate(normals):
                if n:
                    if smooth:
                        norms = [sum(v[k] for v in n) for k in range(3)]
                    else:  # This should be slightly faster for large shapes
                        norms = [n[0][k] for k in range(3)]
                    normals[i] = tuple(Utility.vec_normal(norms))
                else:
                    normals[i] = 0, 0, 0.01

        # keep a copy for speeding up the collision testing of ElevationMap
        self.vertices = pts
        self.normals = normals
        self.tex_coords = texcoords
        self.indices = faces
        self.material = (0.5, 0.5, 0.5, 1.0)

        # Pack points,normals and texcoords into tuples and convert to ctype floats.
        points = [p + n + t for p, n, t in zip(pts, normals, texcoords)]
        self.array_buffer = c_floats(list(itertools.chain(*points)))

        self.ntris = len(faces)
        points = [f[0:3] for f in faces]
        self.element_array_buffer = c_shorts(list(itertools.chain(*points)))