示例#1
0
 def _reset_cue(self):
     # Position and orient the cue
     pos = self.ball['cue'].motion.getWorldTransform().getOrigin()
     p = self.cue.org_pivot
     self.cue.set_pivot(eVector3(p.x, p.y, p.z + SCALE_FACTOR * 0.1))
     self.cue.set_position(eVector3(pos.x, pos.y, pos.z + self.cue.pivot.z))
     self.cue.orient_from_direction()
示例#2
0
 def __init__(self, filename, view):
     self.model = OBJ_vbo(filename)
     self.view = view
     self.morient = Matrix4()
     self.pivot = eVector3()
     self.position = eVector3()
     self.do_transformation_matrix()
示例#3
0
 def getWorldTransform(self):
     p = self.cue.pivot
     t = self.cue.position
     self.cue.set_pivot(eVector3(p.x, p.y, p.z + self.cue.delta * 0.2))
     self.cue.set_position(eVector3(t.x, t.y, t.z + self.cue.delta * 0.2))
     self.cue.do_transformation_matrix()
     mnumpy = array(self.cue.m, 'f')
     self.transform.setFromOpenGLMatrix(mnumpy)
     return self.transform
示例#4
0
    def internal_tick_callback(self, timeStep):
        if self._cue_ball_rest():
            disp = self.world.getDispatcher()
            n = disp.getNumManifolds()
            for i in xrange(n):
                cm = disp.getManifoldByIndexInternal(i)
                contacts = cm.getNumContacts()
                for c in xrange(contacts):
                    obA = cm.getBody0().getUserPointer()
                    obB = cm.getBody1().getUserPointer()
                    if obA == 'Cue' and obB == 'Cue Ball' \
                    or obA == 'Cue Ball' and obB == 'Cue':
                        p = cm.getContactPoint(c)
                        if p.getDistance() < 0.0: # test for penetration
                            # The cue's strike force is calculated from actual
                            # linear velocity applied to the cues orientation vector
                            b = self.cue.body.getLinearVelocity()
                            v = eVector3(b.x, b.y, b.z)
                            d = self.cue.direction if hasattr(self.cue, 'direction') \
                                                   else self.view.dir
                            # get force
                            impuls = v.magnitude() * SCALE_FACTOR * 25.
                            force = bVector3(d.x * impuls,
                                             d.y * impuls,
                                             0.0)
                            # span offset to [0..1]
                            offset = eVector3(self.cue.dx * 4., 0., self.cue.dy * 4.)

                            # calculate offset from cue's position [convert from eye into object space]
                            # TODO: (rewrite this in compact form of vector vs. matrix multiplication)
                            moffset = self.view.orient.inverse() * Matrix4.new_translate(*offset)
                            offset = eVector3(moffset.d, moffset.h, moffset.l)
                            cue = self.ball['cue']
                            cue.body.clearForces()
                            cue.body.applyGravity()
                            cue.body.applyForce(force, bVector3(offset.x, offset.y, offset.z))

                            # Restore cue
                            self._reset_cue()

        def ball_cant_fly(ball):
            # check for flying
            pos = ball.motion.getWorldTransform().getOrigin()
            if pos.z > ball.radius:
                ball.body.applyCentralForce(bVector3(0, 0, -15 * SCALE_FACTOR))
            # check for ball speed
            v = ball.body.getLinearVelocity()
            vel = eVector3(v.x, v.y, v.z)
            if vel.magnitude_squared() > PoolWindow.BALL_MAX_SPEED:
                ball.body.setLinearVelocity(v * 0.9)

        for ball in self.ball.values():
            ball_cant_fly(ball)
示例#5
0
    def __init__(self, filename, view, mass, position=eVector3()):
        super(CueBall, self).__init__(filename, view)
        self.radius = self.model.dimension.z / 2.0
        self.mass = mass
        # Update z pos from radius
        position.z = self.radius

        # Init Transform
        transform = Transform()
        self.position = position
        self.do_transformation_matrix()
        self.mnumpy = array(self.m, 'f')
        transform.setFromOpenGLMatrix(self.mnumpy)

        # The Rigid Body
        mass = self.mass * SCALE_FACTOR
        shape = SphereShape(self.radius)
        i = shape.getLocalInertia(mass) * 0.65
        self.motion = DefaultMotionState()
        self.motion.setWorldTransform(transform)
        self.body = RigidBody.fromConstructionInfo(self.motion,         #  MotionState motion
                                                   shape,               #  CollisionShape shape
                                                   mass,                	#  btScalar mass
                                                   bVector3(i.x, i.y, i.z), #  Vector3 inertia
                                                   transform,           #  Transform worldTransform
                                                   0.2,              	#  btScalar linearDamping
                                                   0.65,              	#  btScalar angularDamping
                                                   0.25,                #  btScalar friction
                                                   0.7,          		#  btScalar restitution
                                                   1.5,                 #  btScalar linearSleepingThreshold
                                                   1.5)                 #  btScalar angularSleepingThreshold

        self.body.setContactProcessingThreshold(0)
        self.body.setCcdMotionThreshold(0)
        self.body.setHitFraction(0.1 * SCALE_FACTOR)
示例#6
0
        def redraw_scene(self, debug=False):
            # table
            self.table.render()

            # rails
            self.rails.render()

            # balls
            for ball in self.ball.values():
                p = ball.motion.getWorldTransform().getOrigin()
                q = ball.motion.getWorldTransform().getRotation()
                a = q.getAxis()
                ball.set_position((p.x, p.y, p.z))
                ball.orient_from_axis_angle(q.getAngle(), eVector3(a.x, a.y, a.z))
                ball.render()

            # cue stick (only if cue ball is resting)
            if self._cue_ball_rest():
                self.cue.render()

            # debug draw
            if debug:
                self.debug.reset()
                self.world.debugDrawWorld()
                glDisable(GL_LIGHTING)
                glBegin(GL_LINES)
                for line in self.debug.lines:
                    glColor3f(*line[6:])
                    glVertex3f(*line[:3])
                    glVertex3f(*line[3:6])
                glEnd()
                glEnable(GL_LIGHTING)
示例#7
0
 def _update_scroll(self, dt):
     distance = self.view.distance * self.zmul
     self.view.set_distance(distance)
     pos = self.ball['cue'].motion.getWorldTransform().getOrigin()
     self.view.set_center(eVector3(pos.x, pos.y, pos.z))
     self._setup_pan()
     self.wheel_step -= 1
     if self.wheel_step == 0:
         pyglet.clock.unschedule(self._update_scroll)
示例#8
0
 def ball_cant_fly(ball):
     # check for flying
     pos = ball.motion.getWorldTransform().getOrigin()
     if pos.z > ball.radius:
         ball.body.applyCentralForce(bVector3(0, 0, -15 * SCALE_FACTOR))
     # check for ball speed
     v = ball.body.getLinearVelocity()
     vel = eVector3(v.x, v.y, v.z)
     if vel.magnitude_squared() > PoolWindow.BALL_MAX_SPEED:
         ball.body.setLinearVelocity(v * 0.9)
示例#9
0
 def render_front_cue(self):
     # Redraw helper top-right (front view)
     glViewport(self.width - self.width / 3, self.height - self.height / 3, self.width / 3, self.height / 3)
     glLoadIdentity()
     eye = eVector3(self.cue.mtransform.d, self.cue.mtransform.h, self.cue.mtransform.l)
     eye += self.cue.direction * 6.
     # render front
     pos = self.ball['cue'].position
     gluLookAt(eye.x, eye.y, eye.z,
               pos.x, pos.y, pos.z,
               0., 0., 1.)
     redraw_scene(self, True)
示例#10
0
 def on_mouse_drag(self, x, y, dx, dy, button, modifiers):
     if button & mouse.LEFT:
         if modifiers & key.MOD_WINDOWS:
             self.view.rotate(dx, dy)
         else:
             self.view.rotate(dx, dy)
             pos = self.ball['cue'].motion.getWorldTransform().getOrigin()
             self.view.set_center(eVector3(pos.x, pos.y, pos.z))
             self.cue.set_position(eVector3(pos.x, pos.y, pos.z + self.cue.pivot.z))
             self.cue.orient_from_direction()
             self._setup_pan()
     elif button & mouse.RIGHT:
         pos = self.ball['cue'].motion.getWorldTransform().getOrigin()
         self.view.set_center(eVector3(pos.x, pos.y, pos.z))
         self.view.zoom(y)
         self._setup_pan()
     elif button & mouse.MIDDLE:
         if modifiers & key.MOD_SHIFT:
             self.cue.move(dx, dy)
         else:
             self.view.pan(dx, dy)
示例#11
0
    def orient_from_direction(self, direction=None):
        '''
        Slightly lower direction vector for pi/32 radian's,
        so cue will render beneath the view's eye position.
        '''
        c = self.view.dir.cross(self.view.up).normalize()
        self.direction = eVector3(*self.view.dir)
        self.direction = self.direction.rotate_around(c, pi / 32.)
        super(CueStick, self).orient_from_direction(self.direction)
        self.update_body_position()

        self.dx = 0.
        self.dy = 0.
示例#12
0
    def __init__(self, filename, view, cball_radius):
        super(CueStick, self).__init__(filename, view)
        self.half = self.model.dimension / 2.0
        self.tip_radius = self.half.x
        self.pivot = eVector3(0, 0, self.half.z + cball_radius)
        self.org_pivot = eVector3(*self.pivot)
        shape = CapsuleShapeZ(self.tip_radius, self.model.dimension.z - self.tip_radius * 2)
        #shape = CylinderShapeZ(bVector3(*self.half))
        transform = Transform()
        transform.setIdentity()
        self.motion = CSMotionState()
        self.motion.cue = self
        self.delta = 0.
        self.dx = 0.
        self.dy = 0.
        self.motion.setWorldTransform(transform)
        self.body = RigidBody.fromConstructionInfo(self.motion,         #  MotionState motion
                                                   shape,               #  CollisionShape shape
                                                   0.0,                 #  btScalar mass
                                                   bVector3(0, 0, 0),   #  Vector3 inertia
                                                   transform,           #  Transform worldTransform
                                                   0.0,                 #  btScalar linearDamping
                                                   0.0,                 #  btScalar angularDamping
                                                   0.0,                 #  btScalar friction
                                                   0.71,                #  btScalar restitution
                                                   0.0,                 #  btScalar linearSleepingThreshold
                                                   0.0)                 #  btScalar angularSleepingThreshold
        self.body.setContactProcessingThreshold(0)
        self.body.setCcdMotionThreshold(0)
        self.body.setHitFraction(0.1 * SCALE_FACTOR)
        self.body.setGravity(bVector3(0, 0, 0))

        # Make it kinematic body with collision contacts generation but no response impulses
        flags = self.body.getCollisionFlags() | CueStick.CF_KINEMATIC_OBJECT | CueStick.CF_NO_CONTACT_RESPONSE
        self.body.setCollisionFlags(flags)
        self.body.setActivationState(DISABLE_DEACTIVATION)
示例#13
0
 def set_pivot(self, pivot):
     self.pivot = eVector3(*pivot)
示例#14
0
 def set_position(self, position):
     self.position = eVector3(*position)
示例#15
0
    def __init__(self, *args, **kwargs):
        super(PoolWindow, self).__init__(*args, **kwargs)
        self.set_size(1680, 1000)
        #self.set_fullscreen()
        self.keys = key.KeyStateHandler()
        self.push_handlers(self.keys)

        # Setup GL
        self.set_vsync(True)
        glClearColor(.15, .15, .15, 1)
        glEnable(GL_DEPTH_TEST)
        glEnable(GL_CULL_FACE)
        glShadeModel(GL_SMOOTH)

        self.lpos1 = (0, 0.5 * SCALE_FACTOR, 1 * SCALE_FACTOR, 0)
        self.lpos2 = (0, -0.5 * SCALE_FACTOR, 1 * SCALE_FACTOR, 0)
        glLightfv(GL_LIGHT0, GL_POSITION, vec(*self.lpos1))
        glLightfv(GL_LIGHT1, GL_POSITION, vec(*self.lpos2))

        glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE)
        glEnable(GL_LIGHTING)
        glEnable(GL_LIGHT0)
        glEnable(GL_LIGHT1)

        # Scroll zoom
        self.wheel_step = PoolWindow.ZOOM_SCROLL_STEP

        # Setup view
        self.view = View(eye=(0, -3 * SCALE_FACTOR, .75 * SCALE_FACTOR),
                         center=(0, 0, -SCALE_FACTOR))
        self.view.set_distance(SCALE_FACTOR)

        # The scene
        self.table = Table('obj/table.obj', self.view)
        self.rails = Rails('obj/rails.obj', self.view)
        self.ball = {}
        self.ball['cue'] = CueBall('obj/ball.obj', self.view, .260)
        self.ball['red'] = CueBall('obj/red.obj', self.view, .260,
                                   eVector3(0, 0.5 * SCALE_FACTOR, 0))
        self.ball['yellow'] = CueBall('obj/yellow.obj', self.view, .260,
                                      eVector3(0, -0.5 * SCALE_FACTOR, 0))
        self.cue = CueStick('obj/cue.obj', self.view, self.ball['cue'].radius)

        self.table.body.setUserPointer("Table")
        self.rails.body.setUserPointer("Rails")
        self.cue.body.setUserPointer("Cue")
        self.ball['cue'].body.setUserPointer("Cue Ball")
        self.ball['red'].body.setUserPointer("Red")
        self.ball['yellow'].body.setUserPointer("Yellow")

        # Set view center
        pos = self.ball['cue'].motion.getWorldTransform().getOrigin()
        self.view.set_center(eVector3(pos.x, pos.y, pos.z))

        # Setup cue (position and orient)
        self._reset_cue()

        # Initialize physics
        self.world = DiscreteDynamicsWorld()
        self.debug = DebugDraw()
        self.world.setDebugDrawer(self.debug)
        self.world.addRigidBody(self.table.body)
        self.world.addRigidBody(self.cue.body)
        self.world.addRigidBody(self.rails.body)
        for ball in self.ball.values():
            self.world.addRigidBody(ball.body)
        self.world.setGravity(bVector3(0, 0, -9.81 * SCALE_FACTOR))

        # Register call-backs
        # A 1/60 call-back to run physics (the same as render)
        pyglet.clock.schedule(self._step)
        # Physic clock callback (usually few times faster than render clock)
        self.world.setInternalTickCallback(self.internal_tick_callback, True)

        self._setup_pan()
        self.topview = False
        self.helper = True

        self.push_handlers(on_key_press=self._on_key_press)
示例#16
0
 def _cue_ball_rest(self):
     vel = self.ball['cue'].body.getLinearVelocity()
     mag = eVector3(vel.x, vel.y, vel.z).magnitude()
     return mag < 0.001