def _move (self, dt, rd): if self._at_rest: return pos = self._pos quat = self._quat vel = self._vel angvel = self._angvel gracc = self.world.gravacc pos1 = pos + vel * dt + gracc * (0.5 * dt**2) vel1 = vel + gracc * dt touch = self.world.below_surface(pos, elev=self._fix_elev) if touch: gpos = self.world.intersect_surface(pos, pos1, elev=self._fix_elev) gnorm = vtof(self.world.elevation(gpos, wnorm=True)[1]) pos1 -= gnorm * (pos1 - gpos).dot(gnorm) * 2 vel1_el = unitv(pos1 - pos) * vel1.length() vel1_el_n = gnorm * vel1_el.dot(gnorm) vel1_el_t = vel1_el - vel1_el_n vel1 = vel1_el_n * self._norm_rest_fac + vel1_el_t * self._tang_rest_fac self._at_rest = (vel1.length() < 0.5) if self._at_rest: pos1 = gpos vel1 = Vec3(0.0, 0.0, 0.0) self.node.setPos(pos1) raxis = unitv(self._angvel) if raxis.length() == 0.0: raxis = Vec3(0.0, 0.0, 1.0) absangvel1 = self._angvel.length() if touch: absangvel1 *= self._tumble_rest_fac dquat = Quat() dquat.setFromAxisAngleRad(absangvel1 * dt, raxis) quat1 = quat * dquat angvel1 = raxis * absangvel1 self.node.setQuat(quat1) self._pos = pos1 self._quat = quat1 self._vel = vel1 self._angvel = angvel1
def __call__(self, task): for moment in self.dataStream: for prevSegment, segment, controlJoint, jointName, endJointName in zip(self.prevFobSegments, segmentsFromMoment(moment), self.controlJoints[:-1], self.joints[:-1], self.joints[1:]): while self.paused: return Task.cont self.prevFobSegments.pop(0) exposedJoint = self.actor.exposeJoint(None, "modelRoot", jointName) exposedEndJoint = self.actor.exposeJoint(None, "modelRoot", endJointName) prevJointSegment = Vec3(exposedEndJoint.getNetTransform().getPos()) - Vec3(exposedJoint.getNetTransform().getPos()) prevSegment.normalize() segment.normalize() prevJointSegment.normalize() axis = prevJointSegment.cross(segment) axis.normalize() import logging # logging.debug("moment: %s" % (moment,)) # logging.debug("segment: %s, prevSegment: %s, prevJointSegment: %s" % (segment, prevSegment, prevJointSegment)) # logging.debug("prevJointSegment: %s" % (prevJointSegment,)) # logging.debug("axis: %s" % (axis,)) angle = prevSegment.angleRad(segment) quat = Quat() quat.setFromAxisAngleRad(angle, axis) controlJoint.setQuat(controlJoint, quat) self.prevFobSegments.append(segment) if not self.stopped: return Task.cont else: return Task.done return Task.done
def _move (self, dt, rd): pos = self._pos quat = self._quat fvel = self._fvel tvel = self._tvel termspeed = self._termspeed gracc = self.world.gravacc fspeed = fvel.length() fdir = unitv(fvel) absdracc = self.world.absgravacc * (fspeed**2 / termspeed**2) if fspeed - absdracc * dt < 0.0: absdracc = (fspeed / dt) * 0.5 dracc = fdir * -absdracc facc = gracc + dracc #facc = Vec3() dfpos = fvel * dt + facc * (0.5 * dt**2) fvel1 = fvel + facc * dt rollspeed = self._rollspeed rollrad = self._rollrad if rollspeed != 0.0 and rollrad != 0.0: rollspeed1 = rollspeed * (1.0 - rd)**2 rollrad1 = rollrad * (1.0 - rd)**2 tdir = unitv(tvel) * (sign(rollspeed * rollrad) or 1) fdir1 = unitv(fvel1) dsroll = rollspeed1 * dt dtquat = Quat() dtquat.setFromAxisAngleRad(dsroll, fdir) tdir1p = Vec3(dtquat.xform(tdir)) tdir1 = unitv(fdir1.cross(tdir1p).cross(fdir1)) tspeed1 = rollspeed1 * rollrad1 dtpos = tvel * dt tvel1 = tdir1 * tspeed1 else: dtpos = Vec3() dtquat = Quat() tvel1 = Vec3() pos1 = pos + dfpos + dtpos self.node.setPos(pos1) fdir1 = unitv(fvel1) paxis = fdir.cross(fdir1) if paxis.length() > 1e-5: paxis.normalize() dspitch = fdir.signedAngleRad(fdir1, paxis) else: paxis = quat.getRight() paxis.normalize() dspitch = 0.0 dfquat = Quat() dfquat.setFromAxisAngleRad(dspitch, paxis) quat1 = quat * dfquat * dtquat self.node.setQuat(quat1) self._pos = pos1 self._quat = quat1 self._fvel = fvel1 self._tvel = tvel1
def move (self, dt): # Base override. # Called by world at end of frame. # Store or pop the turret. pos = self.node.getPos() pos1 = pos vel = Vec3() if self._storepos is not None: speed = self._storespeed tpos = self._storepos if self._stored else self._pos dpos = tpos - pos tdist = dpos.length() if tdist > 1e-3: if speed * dt > tdist: speed = tdist / dt tdir = unitv(dpos) vel = tdir * speed pos1 = pos + vel * dt stfac = ((pos1 - self._storepos).length() / (self._pos - self._storepos).length()) stfac = clamp(stfac, 0.0, 1.0) if self._storedecof: self._storedecof(stfac) # Rotate towards the target intercept direction. idir = self._target_intdir quat = self._aimref_sviw.getQuat() # to self._aimref_base if idir is not None: tdir = self._aimref_base.getRelativeVector(self.world.node, idir) else: tdir = hprtovec(Vec3(self.hcenter, self.pcenter, 0.0)) fdir = quat.getForward() zdir = Vec3(0, 0, 1) rdir = unitv(fdir.cross(zdir)) cturn = atan2(tdir[1], -tdir[0]) tturn = atan2(fdir[1], -fdir[0]) dturn = norm_ang_delta(cturn, tturn) celev = atan2(fdir[2], fdir.getXy().length()) telev = atan2(tdir[2], tdir.getXy().length()) delev = norm_ang_delta(celev, telev) turnrate = self.turnrate if turnrate * dt > abs(dturn): turnrate = abs(dturn) / dt turnrate *= sign(dturn) elevrate = self.elevrate if elevrate * dt > abs(delev): elevrate = abs(delev) / dt elevrate *= sign(delev) angvel = zdir * turnrate + rdir * elevrate # Compute new rotation unconstrained. angspeed = angvel.length() if angspeed > 1e-5: adir = unitv(angvel) dquat = Quat() dquat.setFromAxisAngleRad(angspeed * dt, adir) quat1 = quat * dquat # Limit to movement arc. h, p, r = quat1.getHpr() if isinstance(self.harc, tuple): harc1, harc2 = self.harc else: harc1 = self.hcenter - 0.5 * self.harc harc2 = self.hcenter + 0.5 * self.harc h = pclamp(h, harc1, harc2, -180, 180) if isinstance(self.parc, tuple): parc1, parc2 = self.parc else: parc1 = self.pcenter - 0.5 * self.parc parc2 = self.pcenter + 0.5 * self.parc p = pclamp(p, parc1, parc2, -90, 90, mirror=True) hpr1 = Vec3(h, p, r) else: hpr1 = quat.getHpr() self._update_pos_hpr(pos1, hpr1) # Needed in base class. self._prev_vel = self._vel self._vel = vel self._acc = (self._vel - self._prev_vel) / dt self._prev_angvel = self._angvel self._angvel = angvel self._angacc = (self._angvel - self._prev_angvel) / dt
def __init__ (self, world, name, side, texture=None, pos=None, hpr=None, speed=None, sink=None, damage=None): if pos is None: pos = Point3() if hpr is None: hpr = Vec3() if sink is None: sink = 0.0 if speed is None: speed = 0.0 pos = Point3(pos[0], pos[1], 0.0) self.texture = texture if isinstance(self.modelpath, basestring): shdmodind = 0 elif self.modelpath: shdmodind = min(len(self.modelpath) - 1, 1) else: shdmodind = None Body.__init__(self, world=world, family=self.family, species=self.species, hitforce=(self.strength * 0.1), name=name, side=side, modeldata=AutoProps( path=self.modelpath, shadowpath=self.shdmodelpath, texture=texture, normalmap=self.normalmap, glowmap=self.glowmap, glossmap=self.glossmap, scale=self.modelscale, offset=self.modeloffset, rot=self.modelrot), hitboxdata=self.hitboxdata, hitlight=AutoProps(), hitdebris=self.hitdebris, hitflash=self.hitflash, amblit=True, dirlit=True, pntlit=2, fogblend=True, obright=True, shdshow=True, shdmodind=shdmodind, ltrefl=(self.glossmap is not None), pos=pos, hpr=hpr, vel=speed) self.maxbracc = self.maxspeed / 4.0 # Detect shotdown maps. self._shotdown_texture = self.texture self._shotdown_normalmap = self.normalmap self._shotdown_glowmap = self.glowmap if not isinstance(self.glowmap, Vec4) else None self._shotdown_glossmap = self.glossmap self._shotdown_change_maps = False if isinstance(self.modelpath, basestring): ref_modelpath = self.modelpath elif isinstance(self.modelpath, (tuple, list)): ref_modelpath = self.modelpath[0] else: ref_modelpath = None if ref_modelpath: ref_modeldir = path_dirname(ref_modelpath) ref_modelname = path_basename(ref_modeldir) if self.texture: test_path = self.texture.replace("_tex.", "_burn.") if path_exists("data", test_path): self._shotdown_texture = test_path self._shotdown_change_maps = True if self.normalmap: test_path = join_path(ref_modeldir, ref_modelname + "_burn_nm.png") if path_exists("data", test_path): self._shotdown_normalmap = test_path self._shotdown_change_maps = True if self.glowmap and not isinstance(self.glowmap, Vec4): test_path = join_path(ref_modeldir, ref_modelname + "_burn_gw.png") if path_exists("data", test_path): self._shotdown_glowmap = test_path self._shotdown_change_maps = True if self.glossmap: test_path = join_path(ref_modeldir, ref_modelname + "_burn_gls.png") if path_exists("data", test_path): self._shotdown_glossmap = test_path self._shotdown_change_maps = True # Prepare shotdown model. self._shotdown_modelnode = None if self.sdmodelpath: modelchain = self.sdmodelpath if isinstance(modelchain, basestring): modelchain = [modelchain] ret = load_model_lod_chain( world.vfov, modelchain, texture=self._shotdown_texture, normalmap=self._shotdown_normalmap, glowmap=self._shotdown_glowmap, glossmap=self._shotdown_glossmap, shadowmap=self.world.shadow_texture, scale=self.modelscale, pos=self.modeloffset, hpr=self.modelrot) lnode, models, fardists = ret[:3] lnode.setShader(self.shader) self._shotdown_modelnode = lnode self._shotdown_models = models self._shotdown_fardists = fardists for mlevel, model in enumerate(models): model.setTwoSided(True) # Locally reposition and reorient vehicle such as that # all ground contact points have local z-coordinates zero. # Do this by first rotating ground contact plane around axis # normal to z-axis and to initial ground contact plane normal, # until the ground contact plane normal becomes the z-axis, # then shift ground contact plane along z-axis to become xy-plane. if len(self.groundcontact) != 3: raise StandardError( "There must be exactly 3 ground contact points.") self._platform = self.node.attachNewNode("vehicle-platform") gcf, gcl, gcr = self.groundcontact gcn = unitv((gcl - gcf).cross(gcr - gcf)) zdir = Vec3(0, 0, 1) graxis = gcn.cross(zdir) if graxis.normalize(): gang = gcn.signedAngleRad(zdir, graxis) q = Quat() q.setFromAxisAngleRad(gang, graxis) self._platform.setQuat(q) self._modgndcnts = [] for rgcp in self.groundcontact: rgcp1 = self.node.getRelativePoint(self._platform, rgcp) goffz = rgcp1[2] # equal by construction for all points rgcp1[2] = 0.0 self._modgndcnts.append(rgcp1) self._platform.setPos(gcn * -goffz) self.modelnode.reparentTo(self._platform) # Fix vehicle to the ground, according to contact points. self.sink = sink self._gyro = world.node.attachNewNode("vehicle-gyro-%s" % name) gfix = Vehicle._fix_to_ground(self.world, self._gyro, self._modgndcnts, self.sink, ptod(pos), vtod(hpr)) pos1, hpr1 = gfix[:2] self.node.setPos(ptof(pos1)) self.node.setHpr(vtof(hpr1)) self._prev_gfix = gfix tvelg = speed self._prev_dyn = (tvelg,) width, length, height = self.bbox self.size = (length + width + height) / 3 self._length = length self._size_xy = min(width, length) # Models for detecting moving parts. mvpt_models = list(self.models) if base.with_world_shadows and self.shadow_node is not None: mvpt_models += [self.shadow_node] if self.sdmodelpath: mvpt_models += self._shotdown_models # Detect turning axles. self._axles = [] for model in mvpt_models: axlends = model.findAllMatches("**/axle*") for axlend in axlends: c1, c2 = axlend.getTightBounds() dx, dy, dz = c2 - c1 wheelrad = 0.5 * (abs(dy) + abs(dz)) / 2 self._axles.append((axlend, wheelrad)) # Detect turning tracks. # Use ambient light as shader input for uv-scroll. self._tracks = [] for model in mvpt_models: tracknds = model.findAllMatches("**/track*") for it, tracknd in enumerate(tracknds): spdfac = self.trkspdfac[it] kwargs = dict(self.shader_kwargs) kwargs["uvscrn"] = "INuvscr" shader = make_shader(**kwargs) tracknd.setShader(shader) uvscr = AmbientLight(name=("uvscr-track-%d" % it)) tracknd.setShaderInput(kwargs["uvscrn"], NodePath(uvscr)) uvoff = Vec4() uvscr.setColor(uvoff) self._tracks.append((tracknd, spdfac, uvoff, uvscr)) # Detect lights. # Set up turning on/off through glow factor. self._lights = [] for model in mvpt_models: for lnd in model.findAllMatches("**/lights"): kwargs = dict(self.shader_kwargs) kwargs["glow"] = rgba(255, 255, 255, 1.0) kwargs["glowfacn"] = self.world.shdinp.glowfacn shader = make_shader(**kwargs) lnd.setShader(shader) self._lights.append(lnd) self.set_lights(on=False) if self.engsoundname: self.engine_sound = Sound3D( path=("audio/sounds/%s.ogg" % self.engsoundname), parent=self, maxdist=3000, limnum="hum", volume=self.engmaxvol, loop=True, fadetime=2.5) self.engine_sound.play() else: self.engine_sound = None self.damage = damage or 0.0 self.damage_trails = [] self.launchers = [] self.turrets = [] self.decoys = [] self._prev_path = None self._path_pos = 0.0 self._throttle = 0.0 # Control inputs. self.zero_inputs() # Autopilot constants. self._ap_adjperiod = 1.03 self._ap_adjpfloat = 0.2 # Autopilot state. self.zero_ap() # Route settings. self._route_current_point = None self._route_points = [] self._route_point_inc = 1 self._route_patrol = False self._route_circle = False self._state_info_text = None self._wait_time_state_info = 0.0 base.taskMgr.add(self._loop, "vehicle-loop-%s" % self.name)