void ProjectileSystem::update(ent_ptr<EntityManager> em, ent_ptr<EventManager> events, double dt) { for (auto entity : em->entities_with_components<ProjectileComponent, FrameComponent>()) { ent_ptr<ProjectileComponent> pc = entity.component<ProjectileComponent>(); pc->lifetime -= dt; if (pc->lifetime < 0) { entity.destroy(); continue; } ent_ptr<PosOrientComponent> poc = entity.component<PosOrientComponent>(); const vector3d vel = pc->baseVel + pc->dirVel; poc->pos += vel * dt; //Collide auto pfc = entity.component<FrameComponent>(); CollisionContact c; pfc->frame->GetCollisionSpace()->TraceRay(poc->pos, vel.Normalized(), vel.Length(), &c, 0); Entity* collEnt = static_cast<Entity*>(c.userData1); if (collEnt && *collEnt != pc->owner) { Entity clonk = *collEnt; //auto gc = clonk.component<CollisionMeshComponent>(); //auto fc = clonk.component<FrameComponent>(); //SDL_assert(gc); //SDL_assert(fc); //clonk.destroy(); entity.destroy(); } } }
vector3d TransferPlanner::GetOffsetVel() const { if(m_position.ExactlyEqual(vector3d(0., 0., 0.))) return vector3d(0., 0., 0.); const vector3d pNormal = m_position.Cross(m_velocity); return m_dvPrograde * m_velocity.Normalized() + m_dvNormal * pNormal.Normalized() + m_dvRadial * m_position.Normalized(); }
static void DrawAtmosphereSurface(Graphics::Renderer *renderer, const matrix4x4d &modelView, const vector3d &campos, float rad, Graphics::Material *mat) { const int LAT_SEGS = 20; const int LONG_SEGS = 20; vector3d yaxis = campos.Normalized(); vector3d zaxis = vector3d(1.0,0.0,0.0).Cross(yaxis).Normalized(); vector3d xaxis = yaxis.Cross(zaxis); const matrix4x4d invrot = matrix4x4d::MakeRotMatrix(xaxis, yaxis, zaxis).InverseOf(); renderer->SetTransform(modelView * matrix4x4d::ScaleMatrix(rad, rad, rad) * invrot); // what is this? Well, angle to the horizon is: // acos(planetRadius/viewerDistFromSphereCentre) // and angle from this tangent on to atmosphere is: // acos(planetRadius/atmosphereRadius) ie acos(1.0/1.01244blah) double endAng = acos(1.0/campos.Length())+acos(1.0/rad); double latDiff = endAng / double(LAT_SEGS); double rot = 0.0; float sinCosTable[LONG_SEGS+1][2]; for (int i=0; i<=LONG_SEGS; i++, rot += 2.0*M_PI/double(LONG_SEGS)) { sinCosTable[i][0] = float(sin(rot)); sinCosTable[i][1] = float(cos(rot)); } /* Tri-fan above viewer */ Graphics::VertexArray va(Graphics::ATTRIB_POSITION); va.Add(vector3f(0.f, 1.f, 0.f)); for (int i=0; i<=LONG_SEGS; i++) { va.Add(vector3f( sin(latDiff)*sinCosTable[i][0], cos(latDiff), -sin(latDiff)*sinCosTable[i][1])); } renderer->DrawTriangles(&va, mat, Graphics::TRIANGLE_FAN); /* and wound latitudinal strips */ double lat = latDiff; for (int j=1; j<LAT_SEGS; j++, lat += latDiff) { Graphics::VertexArray v(Graphics::ATTRIB_POSITION); float cosLat = cos(lat); float sinLat = sin(lat); float cosLat2 = cos(lat+latDiff); float sinLat2 = sin(lat+latDiff); for (int i=0; i<=LONG_SEGS; i++) { v.Add(vector3f(sinLat*sinCosTable[i][0], cosLat, -sinLat*sinCosTable[i][1])); v.Add(vector3f(sinLat2*sinCosTable[i][0], cosLat2, -sinLat2*sinCosTable[i][1])); } renderer->DrawTriangles(&v, mat, Graphics::TRIANGLE_STRIP); } }
void Ship::FireWeapon(int num) { if (m_flightState != FLYING) return; std::string prefix(num?"laser_rear_":"laser_front_"); int damage = 0; Properties().Get(prefix+"damage", damage); if (!damage) return; Properties().PushLuaTable(); LuaTable prop(Lua::manager->GetLuaState(), -1); const matrix3x3d &m = GetOrient(); const vector3d dir = m * vector3d(m_gun[num].dir); const vector3d pos = m * vector3d(m_gun[num].pos) + GetPosition(); m_gun[num].temperature += 0.01f; m_gun[num].recharge = prop.Get<float>(prefix+"rechargeTime"); const vector3d baseVel = GetVelocity(); const vector3d dirVel = prop.Get<float>(prefix+"speed") * dir.Normalized(); const Color c(prop.Get<float>(prefix+"rgba_r"), prop.Get<float>(prefix+"rgba_g"), prop.Get<float>(prefix+"rgba_b"), prop.Get<float>(prefix+"rgba_a")); const float lifespan = prop.Get<float>(prefix+"lifespan"); const float width = prop.Get<float>(prefix+"width"); const float length = prop.Get<float>(prefix+"length"); const bool mining = prop.Get<int>(prefix+"mining"); if (prop.Get<int>(prefix+"dual")) { const vector3d orient_norm = m.VectorY(); const vector3d sep = 5.0 * dir.Cross(orient_norm).NormalizedSafe(); Projectile::Add(this, lifespan, damage, length, width, mining, c, pos + sep, baseVel, dirVel); Projectile::Add(this, lifespan, damage, length, width, mining, c, pos - sep, baseVel, dirVel); } else { Projectile::Add(this, lifespan, damage, length, width, mining, c, pos, baseVel, dirVel); } Sound::BodyMakeNoise(this, "Pulse_Laser", 1.0f); lua_pop(prop.GetLua(), 1); LuaEvent::Queue("onShipFiring", this); }
void Ship::FireWeapon(int num) { const ShipType &stype = GetShipType(); if (m_flightState != FLYING) return; const matrix3x3d &m = GetOrient(); const vector3d dir = m * vector3d(stype.gunMount[num].dir); const vector3d pos = m * vector3d(stype.gunMount[num].pos) + GetPosition(); m_gunTemperature[num] += 0.01f; Equip::Type t = m_equipment.Get(Equip::SLOT_LASER, num); const LaserType < = Equip::lasers[Equip::types[t].tableIndex]; m_gunRecharge[num] = lt.rechargeTime; vector3d baseVel = GetVelocity(); vector3d dirVel = lt.speed * dir.Normalized(); if (lt.flags & Equip::LASER_DUAL) { const ShipType::DualLaserOrientation orient = stype.gunMount[num].orient; const vector3d orient_norm = (orient == ShipType::DUAL_LASERS_VERTICAL) ? m.VectorX() : m.VectorY(); const vector3d sep = stype.gunMount[num].sep * dir.Cross(orient_norm).NormalizedSafe(); Projectile::Add(this, t, pos + sep, baseVel, dirVel); Projectile::Add(this, t, pos - sep, baseVel, dirVel); } else Projectile::Add(this, t, pos, baseVel, dirVel); /* // trace laser beam through frame to see who it hits CollisionContact c; GetFrame()->GetCollisionSpace()->TraceRay(pos, dir, 10000.0, &c, this->GetGeom()); if (c.userData1) { Body *hit = static_cast<Body*>(c.userData1); hit->OnDamage(this, damage); } */ Polit::NotifyOfCrime(this, Polit::CRIME_WEAPON_DISCHARGE); Sound::BodyMakeNoise(this, "Pulse_Laser", 1.0f); }
static void MiningLaserSpawnTastyStuff(Frame *f, const SystemBody *asteroid, const vector3d &pos) { Equip::Type t; if (20*Pi::rng.Fixed() < asteroid->GetMetallicity()) { t = Equip::PRECIOUS_METALS; } else if (8*Pi::rng.Fixed() < asteroid->GetMetallicity()) { t = Equip::METAL_ALLOYS; } else if (Pi::rng.Fixed() < asteroid->GetMetallicity()) { t = Equip::METAL_ORE; } else if (Pi::rng.Fixed() < fixed(1,2)) { t = Equip::WATER; } else { t = Equip::RUBBISH; } CargoBody *cargo = new CargoBody(t); cargo->SetFrame(f); cargo->SetPosition(pos); const double x = Pi::rng.Double(); vector3d dir = pos.Normalized(); dir.ArbRotate(vector3d(x, 1-x, 0), Pi::rng.Double()-.5); cargo->SetVelocity(Pi::rng.Double(100.0,200.0) * dir); Pi::game->GetSpace()->AddBody(cargo); }
void Camera::DrawSpike(double rad, const vector3d &viewCoords, const matrix4x4d &viewTransform) { glPushMatrix(); float znear, zfar; Render::GetNearFarClipPlane(znear, zfar); double newdist = znear + 0.5f * (zfar - znear); double scale = newdist / viewCoords.Length(); glTranslatef(float(scale*viewCoords.x), float(scale*viewCoords.y), float(scale*viewCoords.z)); Render::State::UseProgram(0); // face the camera dammit vector3d zaxis = viewCoords.Normalized(); vector3d xaxis = vector3d(0,1,0).Cross(zaxis).Normalized(); vector3d yaxis = zaxis.Cross(xaxis); matrix4x4d rot = matrix4x4d::MakeInvRotMatrix(xaxis, yaxis, zaxis); glMultMatrixd(&rot[0]); glDisable(GL_LIGHTING); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); // XXX WRONG. need to pick light from appropriate turd. GLfloat col[4]; glGetLightfv(GL_LIGHT0, GL_DIFFUSE, col); glColor4f(col[0], col[1], col[2], 1); glBegin(GL_TRIANGLE_FAN); glVertex3f(0,0,0); glColor4f(col[0], col[1], col[2], 0); const float spikerad = float(scale*rad); // bezier with (0,0,0) control points { vector3f p0(0,spikerad,0), p1(spikerad,0,0); float t=0.1f; for (int i=1; i<10; i++, t+= 0.1f) { vector3f p = (1-t)*(1-t)*p0 + t*t*p1; glVertex3fv(&p[0]); } } { vector3f p0(spikerad,0,0), p1(0,-spikerad,0); float t=0.1f; for (int i=1; i<10; i++, t+= 0.1f) { vector3f p = (1-t)*(1-t)*p0 + t*t*p1; glVertex3fv(&p[0]); } } { vector3f p0(0,-spikerad,0), p1(-spikerad,0,0); float t=0.1f; for (int i=1; i<10; i++, t+= 0.1f) { vector3f p = (1-t)*(1-t)*p0 + t*t*p1; glVertex3fv(&p[0]); } } { vector3f p0(-spikerad,0,0), p1(0,spikerad,0); float t=0.1f; for (int i=1; i<10; i++, t+= 0.1f) { vector3f p = (1-t)*(1-t)*p0 + t*t*p1; glVertex3fv(&p[0]); } } glEnd(); glDisable(GL_BLEND); glEnable(GL_LIGHTING); glEnable(GL_DEPTH_TEST); glPopMatrix(); }
void Camera::DrawSpike(double rad, const vector3d &viewCoords, const matrix4x4d &viewTransform) { // draw twinkly star-thing on faraway objects // XXX this seems like a good case for drawing in 2D - use projected position, then the // "face the camera dammit" bits can be skipped if (!m_renderer) return; const double newdist = m_zNear + 0.5f * (m_zFar - m_zNear); const double scale = newdist / viewCoords.Length(); matrix4x4d trans = matrix4x4d::Identity(); trans.Translate(scale*viewCoords.x, scale*viewCoords.y, scale*viewCoords.z); // face the camera dammit vector3d zaxis = viewCoords.Normalized(); vector3d xaxis = vector3d(0,1,0).Cross(zaxis).Normalized(); vector3d yaxis = zaxis.Cross(xaxis); matrix4x4d rot = matrix4x4d::MakeInvRotMatrix(xaxis, yaxis, zaxis); trans = trans * rot; m_renderer->SetDepthTest(false); m_renderer->SetBlendMode(BLEND_ALPHA_ONE); // XXX this is supposed to pick a correct light colour for the object twinkle. // Not quite correct, since it always uses the first light GLfloat col[4]; glGetLightfv(GL_LIGHT0, GL_DIFFUSE, col); col[3] = 1.f; static VertexArray va(ATTRIB_POSITION | ATTRIB_DIFFUSE); va.Clear(); const Color center(col[0], col[1], col[2], col[2]); const Color edges(col[0], col[1], col[2], 0.f); //center va.Add(vector3f(0.f), center); const float spikerad = float(scale*rad); // bezier with (0,0,0) control points { const vector3f p0(0,spikerad,0), p1(spikerad,0,0); float t=0.1f; for (int i=1; i<10; i++, t+= 0.1f) { const vector3f p = (1-t)*(1-t)*p0 + t*t*p1; va.Add(p, edges); } } { const vector3f p0(spikerad,0,0), p1(0,-spikerad,0); float t=0.1f; for (int i=1; i<10; i++, t+= 0.1f) { const vector3f p = (1-t)*(1-t)*p0 + t*t*p1; va.Add(p, edges); } } { const vector3f p0(0,-spikerad,0), p1(-spikerad,0,0); float t=0.1f; for (int i=1; i<10; i++, t+= 0.1f) { const vector3f p = (1-t)*(1-t)*p0 + t*t*p1; va.Add(p, edges); } } { const vector3f p0(-spikerad,0,0), p1(0,spikerad,0); float t=0.1f; for (int i=1; i<10; i++, t+= 0.1f) { const vector3f p = (1-t)*(1-t)*p0 + t*t*p1; va.Add(p, edges); } } glPushMatrix(); m_renderer->SetTransform(trans); m_renderer->DrawTriangles(&va, Graphics::vtxColorMaterial, TRIANGLE_FAN); m_renderer->SetBlendMode(BLEND_SOLID); m_renderer->SetDepthTest(true); glPopMatrix(); }
void BaseSphere::DrawAtmosphereSurface(Graphics::Renderer *renderer, const matrix4x4d &modelView, const vector3d &campos, float rad, Graphics::RenderState *rs, Graphics::Material *mat) { using namespace Graphics; const vector3d yaxis = campos.Normalized(); const vector3d zaxis = vector3d(1.0, 0.0, 0.0).Cross(yaxis).Normalized(); const vector3d xaxis = yaxis.Cross(zaxis); const matrix4x4d invrot = matrix4x4d::MakeRotMatrix(xaxis, yaxis, zaxis).Inverse(); renderer->SetTransform(modelView * matrix4x4d::ScaleMatrix(rad, rad, rad) * invrot); // what is this? Well, angle to the horizon is: // acos(planetRadius/viewerDistFromSphereCentre) // and angle from this tangent on to atmosphere is: // acos(planetRadius/atmosphereRadius) ie acos(1.0/1.01244blah) const double endAng = acos(1.0 / campos.Length()) + acos(1.0 / rad); const double latDiff = endAng / double(LAT_SEGS); double rot = 0.0; float sinTable[LONG_SEGS + 1]; float cosTable[LONG_SEGS + 1]; for (int i = 0; i <= LONG_SEGS; i++, rot += 2.0*M_PI / double(LONG_SEGS)) { sinTable[i] = float(sin(rot)); cosTable[i] = float(cos(rot)); } // Tri-fan above viewer if(!m_TriFanAbove.Valid()) { // VertexBuffer VertexBufferDesc vbd; vbd.attrib[0].semantic = ATTRIB_POSITION; vbd.attrib[0].format = ATTRIB_FORMAT_FLOAT3; vbd.numVertices = LONG_SEGS + 2; vbd.usage = BUFFER_USAGE_STATIC; m_TriFanAbove.Reset(renderer->CreateVertexBuffer(vbd)); } #pragma pack(push, 4) struct PosVert { vector3f pos; }; #pragma pack(pop) PosVert* vtxPtr = m_TriFanAbove->Map<PosVert>(Graphics::BUFFER_MAP_WRITE); vtxPtr[0].pos = vector3f(0.f, 1.f, 0.f); for (int i = 0; i <= LONG_SEGS; i++) { vtxPtr[i + 1].pos = vector3f( sin(latDiff)*sinTable[i], cos(latDiff), -sin(latDiff)*cosTable[i]); } m_TriFanAbove->Unmap(); renderer->DrawBuffer(m_TriFanAbove.Get(), rs, mat, Graphics::TRIANGLE_FAN); // and wound latitudinal strips if (!m_LatitudinalStrips[0].Valid()) { VertexBufferDesc vbd; vbd.attrib[0].semantic = ATTRIB_POSITION; vbd.attrib[0].format = ATTRIB_FORMAT_FLOAT3; vbd.numVertices = (LONG_SEGS + 1) * 2; vbd.usage = BUFFER_USAGE_DYNAMIC; for (int j = 0; j < LAT_SEGS; j++) { // VertexBuffer m_LatitudinalStrips[j].Reset(renderer->CreateVertexBuffer(vbd)); } } double lat = latDiff; for (int j=1; j<LAT_SEGS; j++, lat += latDiff) { const float cosLat = cos(lat); const float sinLat = sin(lat); const float cosLat2 = cos(lat+latDiff); const float sinLat2 = sin(lat+latDiff); vtxPtr = m_LatitudinalStrips[j]->Map<PosVert>(Graphics::BUFFER_MAP_WRITE); vtxPtr[0].pos = vector3f(0.f, 1.f, 0.f); for (int i=0; i<=LONG_SEGS; i++) { vtxPtr[(i*2)+0].pos = vector3f(sinLat*sinTable[i], cosLat, -sinLat*cosTable[i]); vtxPtr[(i*2)+1].pos = vector3f(sinLat2*sinTable[i], cosLat2, -sinLat2*cosTable[i]); } m_LatitudinalStrips[j]->Unmap(); renderer->DrawBuffer(m_LatitudinalStrips[j].Get(), rs, mat, Graphics::TRIANGLE_STRIP); } renderer->GetStats().AddToStatCount(Graphics::Stats::STAT_ATMOSPHERES, 1); }