Example #1
0
  def create3D(self, x=0, y=0, w=0, h=0,
               near=1.0, far=800.0, aspect=60.0, depth=24):
    if w <= 0 or h <= 0:
      w = self.max_width
      h = self.max_height

    self.win_width = w
    self.win_height = h
    self.near = near
    self.far = far

    self.left = x
    self.top = y
    self.right = x + w
    self.bottom = y + h

    self.create_display(x, y, w, h, depth)

    #Setup perspective view
    opengles.glMatrixMode(GL_PROJECTION)
    Utility.load_identity()
    hht = near * math.tan(math.radians(aspect / 2.0))
    hwd = hht * w / h
    opengles.glFrustumf(c_float(-hwd), c_float(hwd),
                        c_float(-hht), c_float(hht),
                        c_float(near), c_float(far))
    opengles.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
    opengles.glMatrixMode(GL_MODELVIEW)
    Utility.load_identity()
Example #2
0
 def perspective(self, w, h, zoom, near=1, far=500):
     opengles.glMatrixMode(GL_PROJECTION)
     Utility.load_identity()
     hht = near * math.tan(math.radians(45.0))
     hwd = hht * w / h
     opengles.glFrustumf(c_float(-hwd), c_float(hwd), c_float(-hht), c_float(hht), c_float(near), c_float(far))
     opengles.glMatrixMode(GL_MODELVIEW)
Example #3
0
File: Draw.py Project: JamesR1/pi3d
def string(font, string, x, y, z, rot, sclx, scly):
  opengles.glNormalPointer(GL_BYTE, 0, RECT_NORMALS)
  Utility.texture_min_mag()
  opengles.glEnableClientState(GL_TEXTURE_COORD_ARRAY)
  opengles.glBindTexture(GL_TEXTURE_2D,font.tex)
  opengles.glEnable(GL_TEXTURE_2D)

  opengles.glDisable(GL_DEPTH_TEST)
  opengles.glDisable(GL_CULL_FACE)
  opengles.glEnable(GL_BLEND)
  opengles.glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA)

  mtrx =(c_float * 16)()
  opengles.glGetFloatv(GL_MODELVIEW_MATRIX,ctypes.byref(mtrx))
  Utility.translatef(x, y, z)
  Utility.rotatef(rot, 0, 0, 1)
  Utility.scalef(sclx, scly, 1)

  for c in range(0,len(string)):
    v = ord(string[c])-32
    w, h, texc, verts = font.chr[v]
    if v > 0:
      opengles.glVertexPointer(3, GL_FLOAT, 0,verts)
      opengles.glTexCoordPointer(2, GL_FLOAT,0,texc)
      opengles.glDrawElements( GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, RECT_TRIANGLES)
    Utility.translatef(w, 0, 0)

  opengles.glLoadMatrixf(mtrx)
  opengles.glDisable(GL_TEXTURE_2D)
  opengles.glDisable(GL_BLEND)
  opengles.glEnable(GL_DEPTH_TEST)
  opengles.glEnable(GL_CULL_FACE)
Example #4
0
    def __init__(
        self,
        camera=None,
        light=None,
        radius=1,
        slices=12,
        sides=12,
        hemi=0.0,
        name="",
        x=0.0,
        y=0.0,
        z=0.0,
        rx=0.0,
        ry=0.0,
        rz=0.0,
        sx=1.0,
        sy=1.0,
        sz=1.0,
        cx=0.0,
        cy=0.0,
        cz=0.0,
        invert=False,
    ):
        """uses standard constructor for Shape extra Keyword arguments:

      *radius*
        radius of sphere
      *slices*
        number of latitude edges
      *hemi*
        if set to 0.5 it will only construct the top half of sphere
      *sides*
        number of sides for Shape._lathe() to use
      *invert*
        normals will face inwards, Texture will need flip=True
    """
        super(Sphere, self).__init__(camera, light, name, x, y, z, rx, ry, rz, sx, sy, sz, cx, cy, cz)

        if VERBOSE:
            print("Creating sphere ...")

        path = []
        # extra points added at poles to reduce distortion (mainly normals)
        st = ((math.pi - 0.002) * (1.0 - hemi)) / slices
        path.append((0.0, radius))
        for r in range(slices + 1):
            x, y = Utility.from_polar_rad(r * st + 0.001, radius)
            path.append((y, x))
        x, y = Utility.from_polar_rad(r * st + 0.002, radius)
        path.append((y, x))
        if invert:
            path.reverse()

        self.radius = radius
        self.slices = slices
        self.hemi = hemi
        self.ttype = GL_TRIANGLES

        self.buf = []
        self.buf.append(self._lathe(path, sides))
Example #5
0
    def __init__(self,
                 camera=None,
                 light=None,
                 radius=1,
                 slices=12,
                 sides=12,
                 hemi=0.0,
                 name="",
                 x=0.0,
                 y=0.0,
                 z=0.0,
                 rx=0.0,
                 ry=0.0,
                 rz=0.0,
                 sx=1.0,
                 sy=1.0,
                 sz=1.0,
                 cx=0.0,
                 cy=0.0,
                 cz=0.0,
                 invert=False):
        """uses standard constructor for Shape extra Keyword arguments:

      *radius*
        radius of sphere
      *slices*
        number of latitude edges
      *hemi*
        if set to 0.5 it will only construct the top half of sphere
      *sides*
        number of sides for Shape._lathe() to use
      *invert*
        normals will face inwards, Texture will need flip=True
    """
        super(Sphere, self).__init__(camera, light, name, x, y, z, rx, ry, rz,
                                     sx, sy, sz, cx, cy, cz)

        if VERBOSE:
            print("Creating sphere ...")

        path = []
        #extra points added at poles to reduce distortion (mainly normals)
        st = ((math.pi - 0.002) * (1.0 - hemi)) / slices
        path.append((0.0, radius))
        for r in range(slices + 1):
            x, y = Utility.from_polar_rad(r * st + 0.001, radius)
            path.append((y, x))
        x, y = Utility.from_polar_rad(r * st + 0.002, radius)
        path.append((y, x))
        if invert:
            path.reverse()

        self.radius = radius
        self.slices = slices
        self.hemi = hemi
        self.ttype = GL_TRIANGLES

        self.buf = []
        self.buf.append(self._lathe(path, sides))
Example #6
0
 def calc_normals(self):
   normals = np.zeros((len(self.array_buffer), 3), dtype="float32") #empty array rights size
   fv = self.array_buffer[self.element_array_buffer,0:3] #expand faces with x,y,z values for each vertex
   #cross product of two edges of triangles
   self.element_normals = np.cross(fv[:,1] - fv[:,0], fv[:,2] - fv[:,0])
   self.element_normals = Utility.normalize_v3(self.element_normals)
   normals[self.element_array_buffer[:,0]] += self.element_normals #add up all normal vectors for a vertex
   normals[self.element_array_buffer[:,1]] += self.element_normals
   normals[self.element_array_buffer[:,2]] += self.element_normals
   return Utility.normalize_v3(normals)
Example #7
0
 def calc_normals(self):
   normals = np.zeros((len(self.array_buffer), 3), dtype="float32") #empty array rights size
   fv = self.array_buffer[self.element_array_buffer,0:3] #expand faces with x,y,z values for each vertex
   #cross product of two edges of triangles
   fn = np.cross(fv[:,1] - fv[:,0], fv[:,2] - fv[:,0])
   fn = Utility.normalize_v3(fn)
   normals[self.element_array_buffer[:,0]] += fn #add up all normal vectors for a vertex
   normals[self.element_array_buffer[:,1]] += fn
   normals[self.element_array_buffer[:,2]] += fn
   return Utility.normalize_v3(normals)
Example #8
0
  def position(self, x, y, z, w=1):
    """ move or rotate the light and change its type

    x,y,z -- location or direction components
    w -- type 0 for directional, 1 for point (default 1)
    """
    mtrx = (ctypes.c_float * 16)()
    opengles.glGetFloatv(GL_MODELVIEW_MATRIX, ctypes.byref(mtrx))
    Utility.load_identity()
    self.xyz = c_floats((x, y, z , w))
    opengles.glLightfv(self.no, GL_POSITION, self.xyz)
    opengles.glLoadMatrixf(mtrx)
Example #9
0
 def orthographic(self, left, right, bottom, top, zoom=1, near=-1, far=10):
     opengles.glMatrixMode(GL_PROJECTION)
     Utility.load_identity()
     # opengles.glOrthof(c_float(-10), c_float(10), c_float(10), c_float(-10.0), c_float(near), c_float(far))
     opengles.glOrthof(
         c_float(left / zoom),
         c_float(right / zoom),
         c_float(bottom / zoom),
         c_float(top / zoom),
         c_float(near),
         c_float(far),
     )
     opengles.glMatrixMode(GL_MODELVIEW)
     Utility.load_identity()
Example #10
0
  def __init__(self,radius=2.0, thickness=0.5, ringrots=6, sides=12, name="",
               x=0.0, y=0.0, z=0.0, rx=0.0, ry=0.0, rz=0.0,
               sx=1.0, sy=1.0, sz=1.0, cx=0.0, cy=0.0, cz=0.0):
    super(Torus,self).__init__(name, x, y, z, rx, ry, rz,
                               sx, sy, sz, cx, cy, cz)

    if VERBOSE:
      print "Creating Torus ..."

    path = []
    st = (math.pi * 2)/ringrots
    for r in range(ringrots + 1):
      x, y = Utility.from_polar_rad(r * st, thickness)
      path.append((radius + y, x))  # TODO: why the reversal?

    self.radius = radius
    self.thickness = thickness
    self.ringrots = ringrots
    self.sides = sides
    self.ttype = GL_TRIANGLES

    results = self.lathe(path)

    self.vertices = c_floats(results[0])
    self.normals = c_floats(results[1])
    self.indices = c_shorts(results[2])
    self.tex_coords = c_floats(results[3])
    self.ssize = results[4]
Example #11
0
  def __init__(self, camera=None, light=None,
               radius=1, slices=12, sides=12, hemi=0.0, name="",
               x=0.0, y=0.0, z=0.0, rx=0.0, ry=0.0, rz=0.0,
               sx=1.0, sy=1.0, sz=1.0, cx=0.0, cy=0.0, cz=0.0):
    """uses standard constructor for Shape extra Keyword arguments:
    
      *radius*
        radius of sphere
      *slices*
        number of latitude edges
      *hemi*
        if set to 0.5 it will only construct the top half of sphere
      *sides*
        number of sides for Shape._lathe() to use
    """
    super(Sphere, self).__init__(camera, light, name, x, y, z, rx, ry, rz,
                                sx, sy, sz, cx, cy, cz)

    if VERBOSE:
      print "Creating sphere ..."

    path = []
    st = (math.pi * (1.0 - hemi)) / slices
    for r in range(slices + 1):
      x, y = Utility.from_polar_rad(r * st, radius)
      path.append((y, x))  # TODO: why is the reversal here?

    self.radius = radius
    self.slices = slices
    self.hemi = hemi
    self.ttype = GL_TRIANGLES

    self.buf = []
    self.buf.append(self._lathe(path, sides))
Example #12
0
File: Torus.py Project: Arexxk/pi3d
  def __init__(self, camera=None, light=None, radius=2.0, thickness=0.5, ringrots=6, sides=12, name="",
               x=0.0, y=0.0, z=0.0, rx=0.0, ry=0.0, rz=0.0,
               sx=1.0, sy=1.0, sz=1.0, cx=0.0, cy=0.0, cz=0.0):
    """uses standard constructor for Shape extra Keyword arguments:
    
      *radius*
        Major radius of torus
      *thickness*
        Minor radius, section through one side of torus
      *ringrots*
        Sides around minor radius circle
      *sides* 
        Number of sides for Shape._lathe() to use
    """
    super(Torus,self).__init__(camera, light, name, x, y, z, rx, ry, rz,
                               sx, sy, sz, cx, cy, cz)

    if VERBOSE:
      print "Creating Torus ..."

    path = []
    st = (math.pi * 2)/ringrots
    for r in range(ringrots + 1):
      x, y = Utility.from_polar_rad(r * st, thickness)
      path.append((radius + y, x))  # TODO: why the reversal?

    self.radius = radius
    self.thickness = thickness
    self.ringrots = ringrots
    self.ttype = GL_TRIANGLES

    self.buf = []
    self.buf.append(self._lathe(path, sides))
Example #13
0
File: Disk.py Project: JamesR1/pi3d
  def __init__(self, radius=1, sides=12, name="", x=0.0, y=0.0, z=0.0,
               rx=0.0, ry=0.0, rz=0.0, sx=1.0, sy=1.0, sz=1.0,
               cx=0.0, cy=0.0, cz=0.0):
    super(Disk, self).__init__(name, x, y, z, rx, ry, rz, sx, sy, sz,
                               cx, cy, cz)

    if VERBOSE:
      print "Creating disk ..."

    self.verts = []
    self.norms = []
    self.inds = []
    self.texcoords = []
    self.ttype = GL_TRIANGLES
    self.sides = sides

    st = math.pi / slices
    self.add_vertex(x, y, z, 0, 1, 0, 0.5, 0.5)
    for r in range(sides+1):
      ca, sa = Utility.from_polar_rad(r * st)
      self.add_vertex(x + radius * sa, y, z + radius * ca,
                      0, 1, 0, sa * 0.5 + 0.5, ca * 0.5 + 0.5)
      # TODO: why the reversal?

    for r in range(sides):
      self.add_tri(0, r + 1, r + 2)

    self.vertices = c_floats(self.verts);
    self.indices = c_shorts(self.inds);
    self.normals = c_floats(self.norms);
    self.tex_coords = c_floats(self.texcoords);
    self.ssize = sides * 3
Example #14
0
  def __init__(self, radius=1, slices=12, sides=12, hemi=0.0, name="",
               x=0.0, y=0.0, z=0.0, rx=0.0, ry=0.0, rz=0.0,
               sx=1.0, sy=1.0, sz=1.0, cx=0.0, cy=0.0, cz=0.0):
    super(Sphere,self).__init__(name, x, y, z, rx, ry, rz,
                                sx, sy, sz, cx, cy, cz)

    if VERBOSE:
      print "Creating sphere ..."

    path = []
    st = (math.pi * (1.0 - hemi)) / slices
    for r in range(slices + 1):
      x, y = Utility.from_polar_rad(r * st, radius)
      path.append((y, x))  # TODO: why is the reversal here?

    self.radius = radius
    self.slices = slices
    self.sides = sides
    self.hemi = hemi
    self.ttype = GL_TRIANGLES

    results = self.lathe(path)

    self.vertices = c_floats(results[0])
    self.normals = c_floats(results[1])
    self.indices = c_shorts(results[2])
    self.tex_coords = c_floats(results[3])
    self.ssize = results[4]
Example #15
0
File: Disk.py Project: wildone/pi3d
    def __init__(self,
                 camera=None,
                 light=None,
                 radius=1,
                 sides=12,
                 name="",
                 x=0.0,
                 y=0.0,
                 z=0.0,
                 rx=0.0,
                 ry=0.0,
                 rz=0.0,
                 sx=1.0,
                 sy=1.0,
                 sz=1.0,
                 cx=0.0,
                 cy=0.0,
                 cz=0.0):
        """uses standard constructor for Shape extra Keyword arguments:

      *radius*
        Radius of disk.
      *sides*
        Number of sides to polygon representing disk.
    """
        super(Disk, self).__init__(camera, light, name, x, y, z, rx, ry, rz,
                                   sx, sy, sz, cx, cy, cz)

        if VERBOSE:
            print("Creating disk ...")

        self.verts = []
        self.norms = []
        self.inds = []
        self.texcoords = []
        self.ttype = GL_TRIANGLES
        self.sides = sides

        st = 2 * pi / sides
        for j in range(-1, 1):
            self.verts.append((0.0, -0.1 * j, 0.0))
            self.norms.append((0.0, -j, 0.0))
            self.texcoords.append((0.5, 0.5))
            for r in range(sides + 1):
                ca, sa = Utility.from_polar_rad(r * st)
                self.verts.append((radius * sa, 0.0, radius * ca))
                self.norms.append((0.0, -j - 0.1 * j, 0.0))
                self.texcoords.append((sa * 0.5 + 0.5, ca * 0.5 + 0.5))
            if j == -1:
                v0, v1, v2 = 0, 1, 2
            else:
                v0, v1, v2 = sides + 2, sides + 4, sides + 3  # i.e. reverse direction to show on back
            for r in range(sides):
                self.inds.append((v0, r + v1, r + v2))

        self.but = []
        self.buf.append(
            Buffer(self, self.verts, self.texcoords, self.inds, self.norms))
Example #16
0
File: Draw.py Project: JamesR1/pi3d
def _draw(verts, tex, x, y, w, h, r, z):
  opengles.glNormalPointer(GL_BYTE, 0, RECT_NORMALS);
  opengles.glVertexPointer(3, GL_BYTE, 0, verts);
  Utility.load_identity()
  Utility.translatef(x, y, z)
  Utility.scalef(w, h, 1)
  if r:
    Utility.rotatef(r, 0, 0, 1)
  with Texture.Loader(tex,RECT_TEX_COORDS,GL_BYTE):
    opengles.glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, RECT_TRIANGLES)
Example #17
0
    def __init__(
        self,
        camera=None,
        light=None,
        radius=1,
        sides=12,
        name="",
        x=0.0,
        y=0.0,
        z=0.0,
        rx=0.0,
        ry=0.0,
        rz=0.0,
        sx=1.0,
        sy=1.0,
        sz=1.0,
        cx=0.0,
        cy=0.0,
        cz=0.0,
    ):
        """uses standard constructor for Shape extra Keyword arguments:
    
      *radius*
        Radius of disk.
      *sides*
        Number of sides to polygon representing disk.
    """
        super(Disk, self).__init__(camera, light, name, x, y, z, rx, ry, rz, sx, sy, sz, cx, cy, cz)

        if VERBOSE:
            print "Creating disk ..."

        self.verts = []
        self.norms = []
        self.inds = []
        self.texcoords = []
        self.ttype = GL_TRIANGLES
        self.sides = sides

        st = 2 * pi / sides
        for j in range(-1, 1):
            self._add_vertex((0.0, -0.1 * j, 0.0), (0.0, -j, 0.0), (0.5, 0.5))
            for r in range(sides + 1):
                ca, sa = Utility.from_polar_rad(r * st)
                self._add_vertex(
                    (radius * sa, 0.0, radius * ca), (0.0, -j - 0.1 * j, 0.0), (sa * 0.5 + 0.5, ca * 0.5 + 0.5)
                )
            if j == -1:
                v0, v1, v2 = 0, 1, 2
            else:
                v0, v1, v2 = sides + 2, sides + 4, sides + 3  # i.e. reverse direction to show on back
            for r in range(sides):
                self._add_tri((v0, r + v1, r + v2))

        self.but = []
        self.buf.append(Buffer(self, self.verts, self.texcoords, self.inds, self.norms))
Example #18
0
 def rotate(self, rx, ry, rz):
   if rz:
     Utility.rotatef(rz, 0, 0, 1)
   if rx:
     Utility.rotatef(rx, 1, 0, 0)
   if ry:
     Utility.rotatef(ry, 0, 1, 0)
    def __init__(self,
                 camera=None,
                 light=None,
                 radius=1,
                 sides=12,
                 name="",
                 x=0.0,
                 y=0.0,
                 z=0.0,
                 rx=0.0,
                 ry=0.0,
                 rz=0.0,
                 sx=1.0,
                 sy=1.0,
                 sz=1.0,
                 cx=0.0,
                 cy=0.0,
                 cz=0.0):
        """uses standard constructor for Shape extra Keyword arguments:

      *radius*
        Radius of disk.
      *sides*
        Number of sides to polygon representing disk.
    """
        super(RoundCorner, self).__init__(camera, light, name, x, y, z, rx, ry,
                                          rz, sx, sy, sz, cx, cy, cz)

        verts = []
        norms = []
        inds = []
        texcoords = []
        self.sides = sides

        st = (pi / 2) / sides
        for j in range(-1, 1):
            verts.append((0.0, -0.1 * j, 0.0))
            norms.append((0.0, -j, 0.0))
            texcoords.append((0.5, 0.5))
            for r in range(0, sides + 1):
                ca, sa = Utility.from_polar_rad(r * st)
                verts.append((radius * sa, 0.0, radius * ca))
                norms.append((0.0, -j - 0.1 * j, 0.0))
                texcoords.append((sa * 0.5 + 0.5, ca * 0.5 + 0.5))
            if j == -1:
                v0, v1, v2 = 0, 1, 2
            else:
                v0, v1, v2 = sides + 2, sides + 4, sides + 3  # i.e. reverse direction to show on back
            for r in range(sides):
                inds.append((v0, r + v1, r + v2))

        self.buf = [Buffer(self, verts, texcoords, inds, norms)]
Example #20
0
    def __init__(self,
                 camera=None,
                 light=None,
                 radius=1,
                 slices=12,
                 sides=12,
                 hemi=0.0,
                 name="",
                 x=0.0,
                 y=0.0,
                 z=0.0,
                 rx=0.0,
                 ry=0.0,
                 rz=0.0,
                 sx=1.0,
                 sy=1.0,
                 sz=1.0,
                 cx=0.0,
                 cy=0.0,
                 cz=0.0):
        """uses standard constructor for Shape extra Keyword arguments:
    
      *radius*
        radius of sphere
      *slices*
        number of latitude edges
      *hemi*
        if set to 0.5 it will only construct the top half of sphere
      *sides*
        number of sides for Shape._lathe() to use
    """
        super(Sphere, self).__init__(camera, light, name, x, y, z, rx, ry, rz,
                                     sx, sy, sz, cx, cy, cz)

        if VERBOSE:
            print "Creating sphere ..."

        path = []
        st = (math.pi * (1.0 - hemi)) / slices
        for r in range(slices + 1):
            x, y = Utility.from_polar_rad(r * st, radius)
            path.append((y, x))  # TODO: why is the reversal here?

        self.radius = radius
        self.slices = slices
        self.hemi = hemi
        self.ttype = GL_TRIANGLES

        self.buf = []
        self.buf.append(self._lathe(path, sides))
Example #21
0
    def __init__(self,
                 camera=None,
                 light=None,
                 radius=2.0,
                 thickness=0.5,
                 ringrots=6,
                 sides=12,
                 name="",
                 x=0.0,
                 y=0.0,
                 z=0.0,
                 rx=0.0,
                 ry=0.0,
                 rz=0.0,
                 sx=1.0,
                 sy=1.0,
                 sz=1.0,
                 cx=0.0,
                 cy=0.0,
                 cz=0.0):
        """uses standard constructor for Shape extra Keyword arguments:
    
      *radius*
        Major radius of torus
      *thickness*
        Minor radius, section through one side of torus
      *ringrots*
        Sides around minor radius circle
      *sides* 
        Number of sides for Shape._lathe() to use
    """
        super(Torus, self).__init__(camera, light, name, x, y, z, rx, ry, rz,
                                    sx, sy, sz, cx, cy, cz)

        if VERBOSE:
            print "Creating Torus ..."

        path = []
        st = (math.pi * 2) / ringrots
        for r in range(ringrots + 1):
            x, y = Utility.from_polar_rad(r * st, thickness)
            path.append((radius + y, x))  # TODO: why the reversal?

        self.radius = radius
        self.thickness = thickness
        self.ringrots = ringrots
        self.ttype = GL_TRIANGLES

        self.buf = []
        self.buf.append(self._lathe(path, sides))
Example #22
0
  def create2D(self, x=0, y=0, w=0, h=0, depth=24, near=-1.0, far=100.0):
    if w <= 0 or h <= 0:
        w = self.max_width
        h = self.max_height

    self.win_width = w
    self.win_height = h
    self.near = near
    self.far = far

    self.left = x
    self.top = y
    self.right = x + w
    self.bottom = y + h

    self.create_display(x, y, w, h, depth)

    opengles.glMatrixMode(GL_PROJECTION)
    Utility.load_identity()
    opengles.glOrthof(c_float(0), c_float(w), c_float(0),
                      c_float(h), c_float(-1), c_float(500))
    opengles.glMatrixMode(GL_MODELVIEW)
    Utility.load_identity()
Example #23
0
  def bounce_collision(self, otherball):
    """work out resultant velocities using 17th.C phsyics"""
    # relative positions
    dx = self.unif[0] - otherball.unif[0]
    dy = self.unif[1] - otherball.unif[1]
    rd = self.radius + otherball.radius
    # check sign of a.b to see if converging
    dotP = Utility.dotproduct(dx, dy, 0,
                              (self.vx - otherball.vx),
                              (self.vy - otherball.vy), 0)
    if dx * dx + dy * dy <= rd * rd and dotP < 0:
      R = otherball.mass / self.mass #ratio of masses
      """Glancing angle for equating angular momentum before and after collision.
      Three more simultaneous equations for x and y components of momentum and
      kinetic energy give:
      """
      if dy:
        D = dx / dy
        delta2y = 2 * (D * self.vx + self.vy -
                       D * otherball.vx - otherball.vy) / (
          (1 + D * D) * (R + 1))
        delta2x = D * delta2y
        delta1y = -1 * R * delta2y
        delta1x = -1 * R * D * delta2y
      elif dx:
        # Same code as above with x and y reversed.
        D = dy / dx
        delta2x = 2 * (D * self.vy + self.vx -
                       D * otherball.vy - otherball.vx) / (
          (1 + D * D) * (R + 1))
        delta2y = D * delta2x
        delta1x = -1 * R * delta2x
        delta1y = -1 * R * D * delta2x
      else:
        delta1x = delta1y = delta2x = delta2y = 0

      self.vx += delta1x
      self.vy += delta1y
      otherball.vx += delta2x
      otherball.vy += delta2y
Example #24
0
File: Disk.py Project: tipam/pi3d
  def __init__(self, camera=None, light=None, radius=1, sides=12, name="", x=0.0, y=0.0, z=0.0,
               rx=0.0, ry=0.0, rz=0.0, sx=1.0, sy=1.0, sz=1.0,
               cx=0.0, cy=0.0, cz=0.0):
    """uses standard constructor for Shape extra Keyword arguments:

      *radius*
        Radius of disk.
      *sides*
        Number of sides to polygon representing disk.
    """
    super(Disk, self).__init__(camera, light, name, x, y, z, rx, ry, rz, sx, sy, sz,
                               cx, cy, cz)

    LOGGER.info("Creating disk ...")

    verts = []
    norms = []
    inds = []
    texcoords = []
    self.sides = sides

    st = 2 * pi / sides
    for j in range(-1, 1):
      verts.append((0.0, -0.1*j, 0.0))
      norms.append((0.0, -j, 0.0))
      texcoords.append((0.5, 0.5))
      for r in range(sides+1):
        ca, sa = Utility.from_polar_rad(r * st)
        verts.append((radius * sa, 0.0, radius * ca))
        norms.append((0.0, -j - 0.1*j, 0.0))
        texcoords.append((sa * 0.5 + 0.5, ca * 0.5 + 0.5))
      if j == -1:
        v0, v1, v2 = 0, 1, 2
      else:
        v0, v1, v2 = sides + 2, sides + 4, sides + 3 # i.e. reverse direction to show on back
      for r in range(sides):
        inds.append((v0, r + v1, r + v2))

    self.buf = [Buffer(self, verts, texcoords, inds, norms)]
Example #25
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 #26
0
 def identity(self):
   Utility.load_identity()
   self.mc = 0
Example #27
0
 def scale(self, sx, sy, sz):
   # TODO: get rid of this.
   Utility.scalef(sx, sy, sz)
Example #28
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 #29
0
mymodel = Model("models/Triceratops/Triceratops.egg",texs,"Triceratops", 0,-1,0, -90,0,0, .005,.005,.005)

# Fetch key presses
mykeys = Keyboard()

# mastrix and rotate variables
rot=0

#create a light
mylight = Light(0,1,1,1,"",10,10,0)
mylight.on()

while 1:
  display.clear()

  Utility.load_identity()
  Utility.translatef(0,0, -40)
  Utility.rotatef(rot, 0, 1, 0)
  rot += 3

  mymodel.draw()

  k = mykeys.read()
  if k >-1:
    if k==112: display.screenshot("Triceratops.jpg")
    elif k==27:
      mykeys.close()
      texs.deleteAll()
      display.destroy()
      break
    else:
Example #30
0
  def draw(self,tex, x, y, z):
    mtrx = (ctypes.c_float*16)()
    opengles.glGetFloatv(GL_MODELVIEW_MATRIX,ctypes.byref(mtrx))
    Utility.translatef(-x, -y, -z)
    Utility.texture_min_mag();
    opengles.glVertexPointer(3, GL_FLOAT, 0, self.vertices)
    opengles.glNormalPointer(GL_FLOAT, 0, self.normals)
    opengles.glEnableClientState(GL_TEXTURE_COORD_ARRAY)
    opengles.glDisable(GL_LIGHTING)
    opengles.glEnable(GL_TEXTURE_2D)

    if self.maptype=="FACES":
        opengles.glTexCoordPointer(2, GL_FLOAT, 0, self.tex_faces)
        opengles.glBindTexture(GL_TEXTURE_2D,tex[0].tex)
        opengles.glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT , self.indtop)

        Utility.texture_min_mag()
        opengles.glBindTexture(GL_TEXTURE_2D,tex[1].tex)
        opengles.glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT , self.indleft)

        Utility.texture_min_mag()
        opengles.glBindTexture(GL_TEXTURE_2D,tex[2].tex)
        opengles.glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT , self.indfront)

        Utility.texture_min_mag()
        opengles.glBindTexture(GL_TEXTURE_2D,tex[3].tex)
        opengles.glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT , self.indright)

        Utility.texture_min_mag()
        opengles.glBindTexture(GL_TEXTURE_2D,tex[4].tex)
        opengles.glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT , self.indback)
        if tex[5] >0:
          Utility.texture_min_mag()
          opengles.glBindTexture(GL_TEXTURE_2D,tex[5].tex)
          opengles.glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT , self.indbot)
    else:
      #load view matrix
      opengles.glTexCoordPointer(2, GL_FLOAT, 0, self.tex_coords)
      opengles.glBindTexture(GL_TEXTURE_2D,tex.tex)
      opengles.glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_SHORT , self.indices)

    opengles.glEnable(GL_LIGHTING)
    opengles.glDisable(GL_TEXTURE_2D)
    #restore to previous matrix
    opengles.glLoadMatrixf(mtrx)
Example #31
0
    def clashTest(self, px, py, pz, rad):
        """Works out if an object at a given location and radius will overlap
    with the map surface. Returns four values:
    
    * boolean whether there is a clash
    * x, y, z components of the normal vector
    * the amount of overlap at the x,z location

    Arguments:
      *px, py, pz*
        Location of object to test in world coordinates.
      *rad*
        Radius of object to test.
    """
        radSq = rad**2
        # adjust for map not set at origin
        px -= self.unif[0]
        py -= self.unif[1]
        pz -= self.unif[2]
        ht = self.height / 255
        halfw = self.width / 2.0
        halfd = self.depth / 2.0
        dx = self.width / self.ix
        dz = self.depth / self.iy

        # work out x and z ranges to check, x0 etc correspond with vertex indices in grid
        x0 = int(math.floor((halfw + px - rad) / dx + 0.5)) - 1
        if x0 < 0: x0 = 0
        x1 = int(math.floor((halfw + px + rad) / dx + 0.5)) + 1
        if x1 > self.ix - 1: x1 = self.ix - 1
        z0 = int(math.floor((halfd + pz - rad) / dz + 0.5)) - 1
        if z0 < 0: z0 = 0
        z1 = int(math.floor((halfd + pz + rad) / dz + 0.5)) + 1
        if z1 > self.iy - 1: z1 = self.iy - 1

        # go through grid around px, pz
        minDist, minLoc = 1000000, (0, 0)
        for i in xrange(x0 + 1, x1):
            for j in xrange(z0 + 1, z1):
                # use the locations stored in the one dimensional vertices matrix
                #generated in __init__. 3 values for each location
                p = j * self.ix + i  # pointer to the start of xyz for i,j in the vertices array
                p1 = j * self.ix + i - 1  # pointer to the start of xyz for i-1,j
                p2 = (j - 1
                      ) * self.ix + i  # pointer to the start of xyz for i, j-1
                vertp = self.buf[0].vertices[p]
                normp = self.buf[0].normals[p]
                # work out distance squared from this vertex to the point
                distSq = (px - vertp[0])**2 + (py - vertp[1])**2 + (
                    pz - vertp[2])**2
                if distSq < minDist:  # this vertex is nearest so keep a record
                    minDist = distSq
                    minLoc = (i, j)
                #now find the distance between the point and the plane perpendicular
                #to the normal at this vertex
                pDist = Utility.dotproduct((px - vertp[0]), (py - vertp[1]),
                                           (pz - vertp[2]), -normp[0],
                                           -normp[1], -normp[2])
                #and the position where the normal from point crosses the plane
                xIsect = px - normp[0] * pDist
                zIsect = pz - normp[2] * pDist

                #if the intersection point is in this rectangle then the x,z values
                #will lie between edges
                if xIsect > self.buf[0].vertices[p1][0] and \
                   xIsect < self.buf[0].vertices[p][0] and \
                   zIsect > self.buf[0].vertices[p2][2] and \
                   zIsect < self.buf[0].vertices[p][2]:
                    pDistSq = pDist**2
                    # finally if the perpendicular distance is less than the nearest so far
                    #keep a record
                    if pDistSq < minDist:
                        minDist = pDistSq
                        minLoc = (i, j)

        gLevel = self.calcHeight(
            px, pz)  #check it hasn't tunnelled through by going fast
        if gLevel > (py - rad):
            minDist = py - gLevel
            minLoc = (int((x0 + x1) / 2), int((z0 + z1) / 2))

        if minDist <= radSq:  #i.e. near enough to clash so return normal
            p = minLoc[1] * self.ix + minLoc[0]
            normp = self.buf[0].normals[p]
            if minDist < 0:
                jump = rad - minDist
            else:
                jump = 0
            return (True, normp[0], normp[1], normp[2], jump)
        else:
            return (False, 0, 0, 0, 0)
Example #32
0
def create(x=None, y=None, w=None, h=None, near=None, far=None,
           fov=DEFAULT_FOV, depth=DEFAULT_DEPTH, background=None,
           tk=False, window_title='', window_parent=None, mouse=False,
           frames_per_second=None):
  """
  Creates a pi3d Display.

  *x*
    Left x coordinate of the display.  If None, defaults to the x coordinate of
    the tkwindow parent, if any.
  *y*
    Top y coordinate of the display.  If None, defaults to the y coordinate of
    the tkwindow parent, if any.
  *w*
    Width of the display.  If None, full the width of the screen.
  *h*
    Height of the display.  If None, full the height of the screen.
  *near*
    This will be used for the default instance of Camera *near* plane
  *far*
    This will be used for the default instance of Camera *far* plane
  *fov*
    Used to define the Camera lens field of view
  *depth*
    The bit depth of the display - must be 8, 16 or 24.
  *background*
    r,g,b,alpha (opacity)
  *tk*
    Do we use the tk windowing system?
  *window_title*
    A window title for tk windows only.
  *window_parent*
    An optional tk parent window.
  *mouse*
    Automatically create a Mouse.
  *frames_per_second*
    Maximum frames per second to render (None means "free running").
  """
  if tk:
    from pi3d.util import TkWin
    if not (w and h):
      # TODO: how do we do full-screen in tk?
      #LOGGER.error("Can't compute default window size when using tk")
      #raise Exception
      # ... just force full screen - TK will automatically fit itself into the screen
      w = 1920
      h = 1180
    tkwin = TkWin.TkWin(window_parent, window_title, w, h)
    tkwin.update()
    if x is None:
      x = tkwin.winx
    if y is None:
      y = tkwin.winy

  else:
    tkwin = None
    x = x or 0
    y = y or 0

  display = Display(tkwin)
  if (w or 0) <= 0:
    w = display.max_width - 2 * x
    if w <= 0:
      w = display.max_width
  if (h or 0) <= 0:
    h = display.max_height - 2 * y
    if h <= 0:
      h = display.max_height
  LOGGER.debug('Display size is w=%d, h=%d', w, h)

  display.frames_per_second = frames_per_second

  if near is None:
    near = DEFAULT_NEAR
  if far is None:
    far = DEFAULT_FAR

  display.width = w
  display.height = h
  display.near = near
  display.far = far
  display.fov = fov

  display.left = x
  display.top = y
  display.right = x + w
  display.bottom = y + h

  display.opengl.create_display(x, y, w, h, depth)
  display.mouse = None

  if mouse:
    from pi3d.Mouse import Mouse
    display.mouse = Mouse(width=w, height=h)
    display.mouse.start()

  # This code now replaced by camera 'lens'
  """opengles.glMatrixMode(GL_PROJECTION)
  Utility.load_identity()
  if is_3d:
    hht = near * math.tan(math.radians(aspect / 2.0))
    hwd = hht * w / h
    opengles.glFrustumf(c_float(-hwd), c_float(hwd), c_float(-hht), c_float(hht),
                        c_float(near), c_float(far))
    opengles.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)
  else:
    opengles.glOrthof(c_float(0), c_float(w), c_float(0), c_float(h),
                      c_float(near), c_float(far))
  """
  opengles.glMatrixMode(GL_MODELVIEW)
  Utility.load_identity()


  if background:
    display.set_background(*background)

  return display
Example #33
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 #34
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)))
Example #35
0
 def hit(self, otherball):
     """Used for pre-checking ball positions."""
     dx = (self.unif[0] + self.vx) - (otherball.unif[0] + otherball.vx)
     dy = (self.unif[1] + self.vy) - (otherball.unif[1] + otherball.vy)
     rd = self.radius + otherball.radius
     return Utility.sqsum(dx, dy) <= (rd * rd)
Example #36
0
File: Ball.py Project: Arexxk/pi3d
 def hit(self, otherball):
   """Used for pre-checking ball positions."""
   dx = (self.unif[0] + self.vx) - (otherball.unif[0] + otherball.vx)
   dy = (self.unif[1] + self.vy) - (otherball.unif[1] + otherball.vy)
   rd = self.radius + otherball.radius
   return Utility.sqsum(dx, dy) <= (rd * rd)
Example #37
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 #38
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, point_size      6   8
        3  u_off, v_off (only 2 used)    9  10
    ===== ============================ ==== ==
    """
    #self.shape = shape
    self.textures = []
    pts = np.array(pts)
    texcoords = np.array(texcoords)
    faces = np.array(faces)

    if normals == None: #i.e. normals will only be generated if explictly None
      LOGGER.debug('Calculating normals ...')

      normals = np.zeros(pts.shape, dtype=pts.dtype) #empty array rights size

      fv = pts[faces] #expand faces with x,y,z values for each vertex
      #cross product of two edges of triangles
      fn = np.cross(fv[:][:][:,1] - fv[:][:][:,0], fv[:][:][:,2] - fv[:][:][:,0])
      fn = Utility.normalize_v3(fn)
      normals[faces[:,0]] += fn #add up all normal vectors for a vertex
      normals[faces[:,1]] += fn
      normals[faces[:,2]] += fn
      Utility.normalize_v3(normals)
    else:
      normals = np.array(normals)
      
    # 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.
    n_verts = len(pts)
    if len(texcoords) != n_verts:
      if len(normals) != n_verts:
        self.N_BYTES = 12 # only use pts
        self.array_buffer = c_floats(pts.reshape(-1).tolist())
      else:
        self.N_BYTES = 24 # use pts and normals
        self.array_buffer = c_floats(np.concatenate((pts, normals),
                            axis=1).reshape(-1).tolist())
    else:
      self.N_BYTES = 32 # use all three NB doesn't check that normals are there
      self.array_buffer = c_floats(np.concatenate((pts, normals, texcoords),
                          axis=1).reshape(-1).tolist())

    self.ntris = len(faces)
    self.element_array_buffer = c_shorts(faces.reshape(-1))
Example #39
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 #40
0
 def translate(self,x,y,z):
   # TODO: get rid of this.
   Utility.translatef(x, y, z)
Example #41
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, point_size      6   8
        3  u_off, v_off (only 2 used)    9  10
    ===== ============================ ==== ==
    """
        #self.shape = shape
        self.textures = []
        pts = np.array(pts, dtype=float)
        texcoords = np.array(texcoords, dtype=float)
        faces = np.array(faces, dtype=int)

        if normals == None:  #i.e. normals will only be generated if explictly None
            LOGGER.debug('Calculating normals ...')

            normals = np.zeros(pts.shape,
                               dtype=float)  #empty array rights size

            fv = pts[faces]  #expand faces with x,y,z values for each vertex
            #cross product of two edges of triangles
            fn = np.cross(fv[:, 1] - fv[:, 0], fv[:, 2] - fv[:, 0])
            fn = Utility.normalize_v3(fn)
            normals[faces[:, 0]] += fn  #add up all normal vectors for a vertex
            normals[faces[:, 1]] += fn
            normals[faces[:, 2]] += fn
            normals = Utility.normalize_v3(normals)
        else:
            normals = np.array(normals)

        # 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)
        self.__pack_data()
Example #42
0
  def clashTest(self, px, py, pz, rad):
    """Works out if an object at a given location and radius will overlap
    with the map surface. Returns four values:

    * boolean whether there is a clash
    * x, y, z components of the normal vector
    * the amount of overlap at the x,z location

    Arguments:
      *px, py, pz*
        Location of object to test in world coordinates.
      *rad*
        Radius of object to test.
    """
    radSq = rad**2
    # adjust for map not set at origin
    px -= self.unif[0]
    py -= self.unif[1]
    pz -= self.unif[2]
    ht = self.height/255
    halfw = self.width/2.0
    halfd = self.depth/2.0
    dx = self.width/self.ix
    dz = self.depth/self.iy

    # work out x and z ranges to check, x0 etc correspond with vertex indices in grid
    x0 = int(math.floor((halfw + px - rad)/dx + 0.5)) - 1
    if x0 < 0: x0 = 0
    x1 = int(math.floor((halfw + px + rad)/dx + 0.5)) + 1
    if x1 > self.ix-1: x1 = self.ix-1
    z0 = int(math.floor((halfd + pz - rad)/dz + 0.5)) - 1
    if z0 < 0: z0 = 0
    z1 = int(math.floor((halfd + pz + rad)/dz + 0.5)) + 1
    if z1 > self.iy-1: z1 = self.iy-1

    # go through grid around px, pz
    minDist, minLoc = 1000000, (0, 0)
    for i in xrange(x0+1, x1):
      for j in xrange(z0+1, z1):
        # use the locations stored in the one dimensional vertices matrix
        #generated in __init__. 3 values for each location
        p = j*self.ix + i # pointer to the start of xyz for i,j in the vertices array
        p1 = j*self.ix + i - 1 # pointer to the start of xyz for i-1,j
        p2 = (j-1)*self.ix + i # pointer to the start of xyz for i, j-1
        vertp = self.buf[0].vertices[p]
        normp = self.buf[0].normals[p]
        # work out distance squared from this vertex to the point
        distSq = (px - vertp[0])**2 + (py - vertp[1])**2 + (pz - vertp[2])**2
        if distSq < minDist: # this vertex is nearest so keep a record
          minDist = distSq
          minLoc = (i, j)
        #now find the distance between the point and the plane perpendicular
        #to the normal at this vertex
        pDist = Utility.dotproduct((px - vertp[0]), (py - vertp[1]), (pz - vertp[2]),
                                  -normp[0], -normp[1], -normp[2])
        #and the position where the normal from point crosses the plane
        xIsect = px - normp[0]*pDist
        zIsect = pz - normp[2]*pDist

        #if the intersection point is in this rectangle then the x,z values
        #will lie between edges
        if xIsect > self.buf[0].vertices[p1][0] and \
           xIsect < self.buf[0].vertices[p][0] and \
           zIsect > self.buf[0].vertices[p2][2] and \
           zIsect < self.buf[0].vertices[p][2]:
          pDistSq = pDist**2
          # finally if the perpendicular distance is less than the nearest so far
          #keep a record
          if pDistSq < minDist:
            minDist = pDistSq
            minLoc = (i,j)

    gLevel = self.calcHeight(px, pz) #check it hasn't tunnelled through by going fast
    if gLevel > (py-rad):
      minDist = py - gLevel
      minLoc = (int((x0+x1)/2), int((z0+z1)/2))

    if minDist <= radSq: #i.e. near enough to clash so return normal
      p = minLoc[1]*self.ix + minLoc[0]
      normp = self.buf[0].normals[p]
      if minDist < 0:
        jump = rad - minDist
      else:
        jump = 0
      return(True, normp[0], normp[1], normp[2],  jump)
    else:
      return (False, 0, 0, 0, 0)