def test_node_prev_transform(): identity = TransformState.make_identity() t1 = TransformState.make_pos((1, 0, 0)) t2 = TransformState.make_pos((2, 0, 0)) t3 = TransformState.make_pos((3, 0, 0)) node = PandaNode("node") assert node.transform == identity assert node.prev_transform == identity assert not node.has_dirty_prev_transform() node.transform = t1 assert node.transform == t1 assert node.prev_transform == identity assert node.has_dirty_prev_transform() node.transform = t2 assert node.transform == t2 assert node.prev_transform == identity assert node.has_dirty_prev_transform() node.reset_prev_transform() assert node.transform == t2 assert node.prev_transform == t2 assert not node.has_dirty_prev_transform() node.transform = t3 assert node.prev_transform == t2 assert node.has_dirty_prev_transform() PandaNode.reset_all_prev_transform() assert node.transform == t3 assert node.prev_transform == t3 assert not node.has_dirty_prev_transform()
def start(self): for component in self.node.data: if isinstance(component, Rigidbody): # Check if parent has rigidbody, and use that node if it does for p_component in self.node.parent.data: if isinstance(p_component, Rigidbody): self.parent_path = p_component.body_path self.update_parent = False if self.parent_path is None: parent_node = BulletRigidBodyNode(self.node.parent.name + "_node") parent_node.set_mass(0) self.parent_path = EComponent.panda_root_node.attach_new_node(parent_node) self.parent_path.setPos(helper.np_vec3_to_panda(self.node.parent.transform.get_world_translation())) rot = np.degrees(self.node.parent.transform.get_world_rotation()) self.parent_path.setHpr(LVector3f(rot[1], rot[0], rot[2])) self.parent_path.setScale(helper.np_vec3_to_panda(self.node.parent.transform.get_world_scale())) # Create constraint child_transform = TransformState.make_pos(LVector3f(0, 0, 0)) node_pos = self.node.transform.get_translation() * self.node.transform.get_world_scale() parent_transform = TransformState.make_pos(helper.np_vec3_to_panda(node_pos)) constraint = BulletConeTwistConstraint(component.body_path.node(), self.parent_path.node(), child_transform, parent_transform) constraint.set_limit(float(self.property_vals["swing_1"]), float(self.property_vals["swing_2"]), float(self.property_vals["max_twist"])) EComponent.physics_world.attachConstraint(constraint)
def start(self): for component in self.node.data: if isinstance(component, Rigidbody): self.rigidbody_component = component radius = float(self.property_vals["radius"]) / 2 shape = BulletSphereShape(radius) component.body_path.node().add_shape( shape, TransformState.make_pos( LVector3f(float(self.property_vals["center"][0]), float(self.property_vals["center"][1]), float(self.property_vals["center"][2]))))
def process_input(self, input, dt): if self.hobot.locked: return self.hobot.process_input(input, dt, self) if self.carrying_joint: pos = self.hobot.hand.get_pos( self.actor) - self.carrying_joint_initial_hobot_hand_pos self.carrying_joint.set_transform( TransformState.make_pos( (self.hobot.model.get_z(), pos[1], -pos[0])).compose(self.carrying_joint_initial_transform)) self.check_interactions()
def setup(self): # Bullet physics world self.worldNP = render.attach_new_node('World') self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug')) self.world = BulletWorld() self.world.set_gravity(LVector3(0, 0, -9.81)) self.world.set_debug_node(self.debugNP.node()) # Vehicle # Steering info self.steering = 0.0 # degrees self.steering_clamp = 45.0 # degrees self.steering_increment = 120.0 # degrees per second # How fast steering relaxes to straight ahead self.steering_relax_factor = 2.0 # How much steering intensity decreases with higher speeds self.steering_speed_reduction_factor = 0.003 # Chassis collision box (note: Bullet uses half-measures) shape = BulletBoxShape(LVector3(0.6, 1.4, 0.5)) ts = TransformState.make_pos(LPoint3(0, 0, 0.5)) self.vehicleNP = self.worldNP.attach_new_node( BulletRigidBodyNode('Vehicle')) self.vehicleNP.node().add_shape(shape, ts) # Set initial position self.vehicleNP.set_pos(0, 70, -10) self.vehicleNP.node().set_mass(800.0) self.vehicleNP.node().set_deactivation_enabled(False) self.world.attach(self.vehicleNP.node()) # Camera floater self.attach_camera_floater() # BulletVehicle self.vehicle = BulletVehicle(self.world, self.vehicleNP.node()) self.world.attach(self.vehicle) # Vehicle model self.yugoNP = loader.load_model('models/yugo/yugo.egg') self.yugoNP.reparent_to(self.vehicleNP) # Right front wheel np = loader.load_model('models/yugo/yugotireR.egg') np.reparent_to(self.worldNP) self.add_wheel(LPoint3( 0.70, 1.05, 0.3), True, np) # Left front wheel np = loader.load_model('models/yugo/yugotireL.egg') np.reparent_to(self.worldNP) self.add_wheel(LPoint3(-0.70, 1.05, 0.3), True, np) # Right rear wheel np = loader.load_model('models/yugo/yugotireR.egg') np.reparent_to(self.worldNP) self.add_wheel(LPoint3( 0.70, -1.05, 0.3), False, np) # Left rear wheel np = loader.load_model('models/yugo/yugotireL.egg') np.reparent_to(self.worldNP) self.add_wheel(LPoint3(-0.70, -1.05, 0.3), False, np) # Load a skybox self.skybox = self.loader.load_model( "samples/shader-terrain/models/skybox.bam") self.skybox.reparent_to(self.render) self.skybox.set_scale(20000) skybox_texture = self.loader.load_texture( "samples/shader-terrain/textures/skybox.jpg") skybox_texture.set_minfilter(SamplerState.FT_linear) skybox_texture.set_magfilter(SamplerState.FT_linear) skybox_texture.set_wrap_u(SamplerState.WM_repeat) skybox_texture.set_wrap_v(SamplerState.WM_mirror) skybox_texture.set_anisotropic_degree(16) self.skybox.set_texture(skybox_texture) skybox_shader = Shader.load(Shader.SL_GLSL, "samples/shader-terrain/skybox.vert.glsl", "samples/shader-terrain/skybox.frag.glsl") self.skybox.set_shader(skybox_shader) # Terrain self.setup_terrain()
def update(self, dt): dt = min(dt, 0.2) # let's just temporarily assume that if we're getting less than 5 fps, dt must be wrong. yaw = self.movement['left'] + self.movement['right'] self.rotate_by(yaw * dt * 60, 0, 0) walk = self.movement['forward'] + self.movement['backward'] start = self.position() cur_pos_ts = TransformState.make_pos(self.position() + self.head_height) if self.on_ground: friction = DEFAULT_FRICTION else: friction = AIR_FRICTION #to debug walk cycle (stay in place) #riction = 0 speed = walk pos = self.position() self.move_by(0, 0, speed) direction = self.position() - pos newpos, self.xz_velocity = Friction(direction, friction).integrate(pos, self.xz_velocity, dt) self.move(newpos) # Cast a ray from just above our feet to just below them, see if anything hits. pt_from = self.position() + Vec3(0, 1, 0) pt_to = pt_from + Vec3(0, -1.1, 0) result = self.world.physics.ray_test_closest(pt_from, pt_to, MAP_COLLIDE_BIT | SOLID_COLLIDE_BIT) # this should return 'on ground' information self.skeleton.update_legs(walk, dt, self.world.scene, self.world.physics) if self.y_velocity.get_y() <= 0 and result.has_hit(): self.on_ground = True self.crouch_impulse = self.y_velocity.y self.y_velocity = Vec3(0, 0, 0) self.move(result.get_hit_pos()) self.skeleton.left_leg_on_ground = True self.skeleton.right_leg_on_ground = True else: self.on_ground = False current_y = Point3(0, self.position().get_y(), 0) y, self.y_velocity = self.integrator.integrate(current_y, self.y_velocity, dt) self.move(self.position() + (y - current_y)) if self.crouching and self.skeleton.crouch_factor < 1: self.skeleton.crouch_factor += (dt*60)/10 self.skeleton.update_legs(0, dt, self.world.scene, self.world.physics) elif not self.crouching and self.skeleton.crouch_factor > 0: self.skeleton.crouch_factor -= (dt*60)/10 self.skeleton.update_legs(0, dt, self.world.scene, self.world.physics) #if self.crouch_impulse < 0: goal = self.position() adj_dist = abs((start - goal).length()) new_pos_ts = TransformState.make_pos(self.position() + self.head_height) sweep_result = self.st_result(cur_pos_ts, new_pos_ts) count = 0 while sweep_result.has_hit() and count < 10: moveby = sweep_result.get_hit_normal() self.xz_velocity = -self.xz_velocity.cross(moveby).cross(moveby) moveby.normalize() moveby *= adj_dist * (1 - sweep_result.get_hit_fraction()) self.move(self.position() + moveby) new_pos_ts = TransformState.make_pos(self.position() + self.head_height) sweep_result = self.st_result(cur_pos_ts, new_pos_ts) count += 1 if self.energy > WALKER_MIN_CHARGE_ENERGY: if self.left_gun_charge < 1: self.energy -= WALKER_ENERGY_TO_GUN_CHARGE[0] self.left_gun_charge += WALKER_ENERGY_TO_GUN_CHARGE[1] else: self.left_gun_charge = math.floor(self.left_gun_charge) if self.right_gun_charge < 1: self.energy -= WALKER_ENERGY_TO_GUN_CHARGE[0] self.right_gun_charge += WALKER_ENERGY_TO_GUN_CHARGE[1] else: self.right_gun_charge = math.floor(self.right_gun_charge) if self.energy < 1: self.energy += WALKER_RECHARGE_FACTOR * (dt) if self.player: self.sights.update(self.left_barrel_joint, self.right_barrel_joint)
def setup(self): self.worldNP = render.attach_new_node('World') # World self.debugNP = self.worldNP.attach_new_node(BulletDebugNode('Debug')) self.debugNP.show() self.world = BulletWorld() self.world.set_gravity(LVector3(0, 0, -9.81)) self.world.set_debug_node(self.debugNP.node()) # Plane shape = BulletPlaneShape(LVector3(0, 0, 1), 0) np = self.worldNP.attach_new_node(BulletRigidBodyNode('Ground')) np.node().add_shape(shape) np.set_pos(0, 0, -1) np.set_collide_mask(BitMask32.all_on()) self.world.attach(np.node()) # Chassis shape = BulletBoxShape(LVector3(0.6, 1.4, 0.5)) ts = TransformState.make_pos(LPoint3(0, 0, 0.5)) np = self.worldNP.attach_new_node(BulletRigidBodyNode('Vehicle')) np.node().add_shape(shape, ts) np.set_pos(0, 0, 1) np.node().set_mass(800.0) np.node().set_deactivation_enabled(False) self.world.attach(np.node()) #np.node().set_ccd_swept_sphere_radius(1.0) #np.node().set_ccd_motion_threshold(1e-7) # Vehicle self.vehicle = BulletVehicle(self.world, np.node()) self.vehicle.set_coordinate_system(ZUp) self.world.attach(self.vehicle) self.yugoNP = loader.load_model('models/yugo/yugo.egg') self.yugoNP.reparent_to(np) # Right front wheel np = loader.load_model('models/yugo/yugotireR.egg') np.reparent_to(self.worldNP) self.add_wheel(LPoint3( 0.70, 1.05, 0.3), True, np) # Left front wheel np = loader.load_model('models/yugo/yugotireL.egg') np.reparent_to(self.worldNP) self.add_wheel(LPoint3(-0.70, 1.05, 0.3), True, np) # Right rear wheel np = loader.load_model('models/yugo/yugotireR.egg') np.reparent_to(self.worldNP) self.add_wheel(LPoint3( 0.70, -1.05, 0.3), False, np) # Left rear wheel np = loader.load_model('models/yugo/yugotireL.egg') np.reparent_to(self.worldNP) self.add_wheel(LPoint3(-0.70, -1.05, 0.3), False, np) # Steering info self.steering = 0.0 # degree self.steeringClamp = 45.0 # degree self.steeringIncrement = 120.0 # degree per second
def update(self, world, dt): dirty = self.mouse_dirty old_pos = self.node.get_pos() h = self.node.get_h() new_velocity = self.velocity + (world.gravity * dt) if self.resting: if not (self.motion['forward'] ^ self.motion['backward']): self.motor_power /= 1.5 if abs(self.motor_power) < 0.05: self.motor_power = 0.0 elif self.motion['forward']: self.motor_power = min(max(self.motor_power, 0) + (dt / self.WALK_ACCEL), 1.0) elif self.motion['backward']: self.motor_power = max(min(self.motor_power, 0) - (dt / self.WALK_ACCEL), -1.0) else: self.motor_power /= 1.5 if abs(self.motor_power) < 0.05: self.motor_power = 0.0 if not (self.motion['left'] ^ self.motion['right']): self.turn_power /= 1.25 if abs(self.turn_power) < 0.05: self.turn_power = 0.0 elif self.motion['left']: self.turn_power = min(max(self.turn_power, 0) + (dt / self.TURN_ACCEL), 1.0) elif self.motion['right']: self.turn_power = max(min(self.turn_power, 0) - (dt / self.TURN_ACCEL), -1.0) # Dampen the turn motor while walking. self.turn_power /= ((abs(self.motor_power) * self.TURN_DAMPER) + 1.0) if (abs(self.turn_power) + abs(self.motor_power)) > 0: dirty = True h += self.TURN_SPEED * dt * self.turn_power self.node.set_h(h) if self.motor_power != 0: # Panda's heading starts along the Y axis, so we need to rotate 90 degrees to start along X. x = math.cos(math.radians(h + 90)) * self.WALK_SPEED * self.motor_power y = math.sin(math.radians(h + 90)) * self.WALK_SPEED * self.motor_power new_velocity.set_x(x) new_velocity.set_y(y) else: new_velocity.set_x(0) new_velocity.set_y(0) new_pos = old_pos + (new_velocity * dt) # Cast a ray below our feet to determine if we're resting on an object. start = new_pos + Vec3(0, 0, 1.5) end = new_pos + Vec3(0, 0, -2.0) result = world.physics.ray_test_closest(start, end, Collision.SOLID) if result.has_hit(): self.resting = True new_velocity.set_z(0) new_pos.set_z(result.hit_pos.z + 1.52) else: self.resting = False count = 0 max_tries = 3 shape = self.body.get_shape(0) from_ts = TransformState.make_pos(old_pos) to_ts = TransformState.make_pos(new_pos) result = world.physics.sweep_test_closest(shape, from_ts, to_ts, Collision.SOLID, 0) while result.has_hit() and count < max_tries: normal = result.hit_normal slide = 1.0 - result.hit_fraction - 0.01 # First, move us back out of contact with whatever we hit. direction = new_pos - old_pos old_pos = old_pos + (direction * (result.hit_fraction - 0.01)) # This is a safety check to make sure we actually moved out of the collision. to_ts = TransformState.make_pos(old_pos) result = world.physics.sweep_test_closest(shape, from_ts, to_ts, Collision.SOLID, 0) if result.has_hit(): print("UH OH") # Adjust the velocity to be along the plane perpendicular to the normal of the hit. new_velocity = -new_velocity.cross(normal).cross(normal) if new_velocity.z < 0.01: self.resting = True new_velocity.set_z(0) # Now try to slide along that plane the rest of the way. new_pos = old_pos + (new_velocity * dt * slide) from_ts = TransformState.make_pos(old_pos) to_ts = TransformState.make_pos(new_pos) result = world.physics.sweep_test_closest(shape, from_ts, to_ts, Collision.SOLID, 0) if result.hit_fraction < 0.0001: print("NO ROOM TO SLIDE", result.node, result.hit_normal, new_velocity, slide) break count += 1 if count >= max_tries: new_pos = old_pos print("FAIL", normal, new_velocity, result.hit_fraction) if new_velocity.length() < 0.001: new_velocity = Vec3() self.resting = True self.node.set_pos(new_pos) self.velocity = new_velocity self.mouse_dirty = False if old_pos != new_pos: dirty = True return dirty