Exemple #1
0
void Ship::AIAccelToModelRelativeVelocity(const vector3d &v)
{
	vector3d difVel = v - GetVelocity() * GetOrient();		// required change in velocity
	vector3d maxThrust = GetMaxThrust(difVel);
	vector3d maxFrameAccel = maxThrust * (Pi::game->GetTimeStep() / GetMass());

	SetThrusterState(0, is_zero_exact(maxFrameAccel.x) ? 0.0 : difVel.x / maxFrameAccel.x);
	SetThrusterState(1, is_zero_exact(maxFrameAccel.y) ? 0.0 : difVel.y / maxFrameAccel.y);
	SetThrusterState(2, is_zero_exact(maxFrameAccel.z) ? 0.0 : difVel.z / maxFrameAccel.z);	// use clamping
}
Exemple #2
0
void SpaceStation::TimeStepUpdate(const float timeStep)
{
	// rotate the thing
	double len = m_type->angVel * timeStep;
	if (!is_zero_exact(len)) {
		matrix3x3d r = matrix3x3d::RotateY(-len);		// RotateY is backwards
		SetOrient(r * GetOrient());
	}
	m_oldAngDisplacement = len;

	// reposition the ships that are docked or docking here
	for (int i=0; i<m_type->numDockingPorts; i++) {
		const shipDocking_t &dt = m_shipDocking[i];
		if (!dt.ship) { //free
			m_navLights->SetColor(i+1, NavLights::NAVLIGHT_GREEN);
			continue;
		}
		if (dt.stage == 1) //reserved
			m_navLights->SetColor(i+1, NavLights::NAVLIGHT_YELLOW);
		if (dt.ship->GetFlightState() == Ship::FLYING)
			continue;
		PositionDockedShip(dt.ship, i);
		m_navLights->SetColor(i+1, NavLights::NAVLIGHT_RED); //docked
	}

	if (m_doorAnimation)
		GetModel()->UpdateAnimations();
}
Exemple #3
0
void Frame::UpdateOrbitRails(double time, double timestep)
{
	m_oldPos = m_pos;
	m_oldAngDisplacement = m_angSpeed * timestep;

	// update frame position and velocity
	if (m_parent && m_sbody && !IsRotFrame()) {
		m_pos = m_sbody->orbit.OrbitalPosAtTime(time);
		vector3d pos2 = m_sbody->orbit.OrbitalPosAtTime(time+timestep);
		m_vel = (pos2 - m_pos) / timestep;
	}
	// temporary test thing
	else m_pos = m_pos + m_vel * timestep;
	
	// update frame rotation
	double ang = m_angSpeed * timestep;		// hmm. cumulative inaccuracy? worse!
	if (!is_zero_exact(ang)) {			// frequently used with e^-10 etc
		matrix3x3d rot = matrix3x3d::RotateY(-ang);		// RotateY is backwards
		m_orient = m_orient * rot;		// angvel always +y
	}
	UpdateRootRelativeVars();			// update root-relative pos/vel/orient

	for (ChildIterator it = m_children.begin(); it != m_children.end(); ++it)
		(*it)->UpdateOrbitRails(time, timestep);
}
Exemple #4
0
void Frame::UpdateOrbitRails(double time, double timestep)
{
	m_oldPos = m_pos;
	m_oldAngDisplacement = m_angSpeed * timestep;

	// update frame position and velocity
	if (m_parent && m_sbody && !IsRotFrame()) {
		m_pos = m_sbody->GetOrbit().OrbitalPosAtTime(time);
		vector3d pos2 = m_sbody->GetOrbit().OrbitalPosAtTime(time+timestep);
		m_vel = (pos2 - m_pos) / timestep;
	}
	// temporary test thing
	else m_pos = m_pos + m_vel * timestep;
	
	// update frame rotation
	double ang = fmod(m_angSpeed * time, 2.0 * M_PI);
	if (!is_zero_exact(ang)) {			// frequently used with e^-10 etc
		matrix3x3d rot = matrix3x3d::RotateY(-ang);		// RotateY is backwards
		m_orient = m_initialOrient * rot;		// angvel always +y
	}
	UpdateRootRelativeVars();			// update root-relative pos/vel/orient

	for (Frame* kid : m_children)
		kid->UpdateOrbitRails(time, timestep);
}
Exemple #5
0
bool Frustum::ProjectPoint(const vector3d &in, vector3d &out) const
{
	// see the OpenGL documentation
	// or http://www.songho.ca/opengl/gl_transform.html
	// or http://cgit.freedesktop.org/mesa/glu/tree/src/libutil/project.c (gluProject implementation from Mesa)

	const double * const M = m_modelMatrix.Data();
	const double * const P = m_projMatrix.Data();

	const double vcam[4] = { // camera space
		in.x*M[0] + in.y*M[4] + in.z*M[ 8] + M[12],
		in.x*M[1] + in.y*M[5] + in.z*M[ 9] + M[13],
		in.x*M[2] + in.y*M[6] + in.z*M[10] + M[14],
		in.x*M[3] + in.y*M[7] + in.z*M[11] + M[15]
	};
	const double vclip[4] = { // clip space
		vcam[0]*P[0] + vcam[1]*P[4] + vcam[2]*P[ 8] + vcam[3]*P[12],
		vcam[0]*P[1] + vcam[1]*P[5] + vcam[2]*P[ 9] + vcam[3]*P[13],
		vcam[0]*P[2] + vcam[1]*P[6] + vcam[2]*P[10] + vcam[3]*P[14],
		vcam[0]*P[3] + vcam[1]*P[7] + vcam[2]*P[11] + vcam[3]*P[15]
	};

	if (is_zero_exact(vclip[3])) { return false; }

	const double w = vclip[3];
	out.x = (vclip[0] / w) * 0.5 + 0.5;
	out.y = (vclip[1] / w) * 0.5 + 0.5;
	out.z = (vclip[2] / w) * 0.5 + 0.5;

	return true;
}
Exemple #6
0
// returns direction in ship's frame from this ship to target lead position
vector3d Ship::AIGetLeadDir(const Body *target, const vector3d& targaccel, int gunindex)
{
	assert(target);
	if (ScopedTable(m_equipSet).CallMethod<int>("OccupiedSpace", "laser_front") == 0)
		return target->GetPositionRelTo(this).Normalized();

	const vector3d targpos = target->GetPositionRelTo(this);
	const vector3d targvel = target->GetVelocityRelTo(this);
	// todo: should adjust targpos for gunmount offset

	double projspeed = 0;
	Properties().Get(gunindex?"laser_rear_speed":"laser_front_speed", projspeed);

	vector3d leadpos;
	// avoid a divide-by-zero floating point exception (very nearly zero is ok)
	if( !is_zero_exact(projspeed) ) {
		// first attempt
		double projtime = targpos.Length() / projspeed;
		leadpos = targpos + targvel*projtime + 0.5*targaccel*projtime*projtime;

		// second pass
		projtime = leadpos.Length() / projspeed;
		leadpos = targpos + targvel*projtime + 0.5*targaccel*projtime*projtime;
	} else {
		// default
		leadpos = targpos;
	}

	return leadpos.Normalized();
}
Exemple #7
0
// Input: direction in ship's frame, doesn't need to be normalized
// Approximate positive angular velocity at match point
// Applies thrust directly
// old: returns whether it can reach that direction in this frame
// returns angle to target
double Ship::AIFaceDirection(const vector3d &dir, double av)
{
	double maxAccel = m_type->angThrust / GetAngularInertia();		// should probably be in stats anyway

	vector3d head = (dir * GetOrient()).Normalized();		// create desired object-space heading
	vector3d dav(0.0, 0.0, 0.0);	// desired angular velocity

	double ang = 0.0;
	if (head.z > -0.99999999)
	{
		ang = acos (Clamp(-head.z, -1.0, 1.0));		// scalar angle from head to curhead
		double iangvel = av + calc_ivel_pos(ang, 0.0, maxAccel);	// ideal angvel at current time

		// Normalize (head.x, head.y) to give desired angvel direction
		if (head.z > 0.999999) head.x = 1.0;
		double head2dnorm = 1.0 / sqrt(head.x*head.x + head.y*head.y);		// NAN fix shouldn't be necessary if inputs are normalized
		dav.x = head.y * head2dnorm * iangvel;
		dav.y = -head.x * head2dnorm * iangvel;
	}
	const vector3d cav = GetAngVelocity() * GetOrient();				// current obj-rel angvel
	const double frameAccel = maxAccel * Pi::game->GetTimeStep();
	vector3d diff = is_zero_exact(frameAccel) ? vector3d(0.0) : (dav - cav) / frameAccel;	// find diff between current & desired angvel

	// If the player is pressing a roll key, don't override roll.
	// XXX this really shouldn't be here. a better way would be to have a
	// field in Ship describing the wanted angvel adjustment from input. the
	// baseclass version in Ship would always be 0. the version in Player
	// would be constructed from user input. that adjustment could then be
	// considered by this method when computing the required change
	if (IsType(Object::PLAYER) && (KeyBindings::rollLeft.IsActive() || KeyBindings::rollRight.IsActive()))
		diff.z = m_angThrusters.z;
	SetAngThrusterState(diff);
	return ang;
}
Exemple #8
0
// returns direction in ship's frame from this ship to target lead position
vector3d Ship::AIGetLeadDir(const Body *target, const vector3d& targaccel, int gunindex)
{
	assert(target);
	if (m_equipment.Get(Equip::SLOT_LASER) == Equip::NONE)
		return target->GetPositionRelTo(this).Normalized();

	const vector3d targpos = target->GetPositionRelTo(this);
	const vector3d targvel = target->GetVelocityRelTo(this);
	// todo: should adjust targpos for gunmount offset

	const int laser = Equip::types[m_equipment.Get(Equip::SLOT_LASER, gunindex)].tableIndex;
	const double projspeed = Equip::lasers[laser].speed;

	vector3d leadpos;
	// avoid a divide-by-zero floating point exception (very nearly zero is ok)
	if( !is_zero_exact(projspeed) ) {
		// first attempt
		double projtime = targpos.Length() / projspeed;
		leadpos = targpos + targvel*projtime + 0.5*targaccel*projtime*projtime;

		// second pass
		projtime = leadpos.Length() / projspeed;
		leadpos = targpos + targvel*projtime + 0.5*targaccel*projtime*projtime;
	} else {
		// default
		leadpos = targpos;
	}

	return leadpos.Normalized();
}
static void set_master_volume(const bool muted, const float volume)
{
	Sound::Pause(muted || is_zero_exact(volume));
	Sound::SetMasterVolume(volume);
	Pi::config->SetFloat("MasterVolume", volume);
	Pi::config->SetInt("MasterMuted", muted ? 1 : 0);
	Pi::config->Save();
}
static void set_music_volume(const bool muted, const float volume)
{
	Pi::GetMusicPlayer().SetEnabled(!(muted || is_zero_exact(volume)));
	Pi::GetMusicPlayer().SetVolume(volume);
	Pi::config->SetFloat("MusicVolume", volume);
	Pi::config->SetInt("MusicMuted", muted ? 1 : 0);
	Pi::config->Save();
}
Exemple #11
0
void SpaceStation::UpdateInterpTransform(double alpha)
{
	double len = m_oldAngDisplacement * (1.0-alpha);
	if (!is_zero_exact(len)) {
		matrix3x3d rot = matrix3x3d::RotateY(len);		// RotateY is backwards
		m_interpOrient = rot * GetOrient();
	}
	else m_interpOrient = GetOrient();
	m_interpPos = GetPosition();
}
CargoBody::CargoBody(const LuaRef& cargo, float selfdestructTimer): m_cargo(cargo)
{
	SetModel("cargo");
	Init();
	SetMass(1.0);
	m_selfdestructTimer = selfdestructTimer; // number of seconds to live

	if (is_zero_exact(selfdestructTimer)) // turn off self destruct
		m_hasSelfdestruct = false;
}
Exemple #13
0
void Frame::SetOrient(const matrix3x3d &m, double time) {
	m_orient = m;
	double ang = fmod(m_angSpeed * time, 2.0 * M_PI);
	if (!is_zero_exact(ang)) {			// frequently used with e^-10 etc
		matrix3x3d rot = matrix3x3d::RotateY(ang);		// RotateY is backwards
		m_initialOrient = m_orient * rot;		// angvel always +y
	} else {
		m_initialOrient = m_orient;
	}
}
Exemple #14
0
void SpaceStation::TimeStepUpdate(const float timeStep)
{
	// rotate the thing 
	double len = m_type->angVel * timeStep;
	if (!is_zero_exact(len)) {
		matrix3x3d r = matrix3x3d::RotateY(-len);		// RotateY is backwards
		SetOrient(r * GetOrient());
	}
	m_oldAngDisplacement = len;

	// reposition the ships that are docked or docking here
	for (int i=0; i<m_type->numDockingPorts; i++) {
		const shipDocking_t &dt = m_shipDocking[i];
		if (!dt.ship || dt.stage == 1) continue;
		if (dt.ship->GetFlightState() == Ship::FLYING) continue;
		PositionDockedShip(dt.ship, i);
	}
}
Exemple #15
0
void Frame::UpdateInterpTransform(double alpha)
{
	m_interpPos = alpha*m_pos + (1.0-alpha)*m_oldPos;

	double len = m_oldAngDisplacement * (1.0-alpha);
	if (!is_zero_exact(len)) {			// very small values are normal here
		matrix3x3d rot = matrix3x3d::RotateY(len);		// RotateY is backwards
		m_interpOrient = m_orient * rot;
	}
	else m_interpOrient = m_orient;

	if (!m_parent) ClearMovement();
	else {
		m_rootInterpPos = m_parent->m_rootInterpOrient * m_interpPos
			+ m_parent->m_rootInterpPos;
		m_rootInterpOrient = m_parent->m_rootInterpOrient * m_interpOrient;
	}

	for (ChildIterator it = m_children.begin(); it != m_children.end(); ++it)
		(*it)->UpdateInterpTransform(alpha);
}
Exemple #16
0
void Frame::UpdateInterpTransform(double alpha)
{
	PROFILE_SCOPED()
	m_interpPos = alpha*m_pos + (1.0-alpha)*m_oldPos;

	double len = m_oldAngDisplacement * (1.0-alpha);
	if (!is_zero_exact(len)) {			// very small values are normal here
		matrix3x3d rot = matrix3x3d::RotateY(len);		// RotateY is backwards
		m_interpOrient = m_orient * rot;
	}
	else m_interpOrient = m_orient;

	if (!m_parent) ClearMovement();
	else {
		m_rootInterpPos = m_parent->m_rootInterpOrient * m_interpPos
			+ m_parent->m_rootInterpPos;
		m_rootInterpOrient = m_parent->m_rootInterpOrient * m_interpOrient;
	}

	for (Frame* kid : m_children)
		kid->UpdateInterpTransform(alpha);
}
bool Screen::Project(const vector3d &in, vector3d &out)
{
	PROFILE_SCOPED()
	// implements gluProject (see the OpenGL documentation or the Mesa implementation of gluProject)
	const float * const M = modelMatrix.Data();
	const float * const P = projMatrix.Data();

	const double vcam[4] = { // camera space
		in.x*M[0] + in.y*M[4] + in.z*M[ 8] + M[12],
		in.x*M[1] + in.y*M[5] + in.z*M[ 9] + M[13],
		in.x*M[2] + in.y*M[6] + in.z*M[10] + M[14],
		in.x*M[3] + in.y*M[7] + in.z*M[11] + M[15]
	};
	const double vclip[4] = { // clip space
		vcam[0]*P[0] + vcam[1]*P[4] + vcam[2]*P[ 8] + vcam[3]*P[12],
		vcam[0]*P[1] + vcam[1]*P[5] + vcam[2]*P[ 9] + vcam[3]*P[13],
		vcam[0]*P[2] + vcam[1]*P[6] + vcam[2]*P[10] + vcam[3]*P[14],
		vcam[0]*P[3] + vcam[1]*P[7] + vcam[2]*P[11] + vcam[3]*P[15]
	};

	if (is_zero_exact(vclip[3])) { return false; }

	const double w = vclip[3];

	const double v[3] = {
		(vclip[0] / w) * 0.5 + 0.5,
		(vclip[1] / w) * 0.5 + 0.5,
		(vclip[2] / w) * 0.5 + 0.5
	};

	out.x = v[0] * viewport[2] + viewport[0];
	out.y = v[1] * viewport[3] + viewport[1];
	out.z = v[2];

	// map to pixels
	out.x = out.x * width * invRealWidth;
	out.y = GetHeight() - out.y * height * invRealHeight;
	return true;
}
Exemple #18
0
static bool ShipIsUnbuyable(const std::string &id)
{
	const ShipType &t = ShipType::types[id];
	return is_zero_exact(t.baseprice);
}