//ZZZ unpleasant static void hitCallback(CollisionContact* c) { auto& ent1 = *static_cast<Entity*>(c->userData1); auto& ent2 = *static_cast<Entity*>(c->userData2); auto dc1 = ent1.component<DynamicsComponent>(); auto dc2 = ent2.component<DynamicsComponent>(); auto poc1 = ent1.component<PosOrientComponent>(); auto poc2 = ent2.component<PosOrientComponent>(); auto mc1 = ent1.component<MassComponent>(); auto mc2 = ent2.component<MassComponent>(); const double coeff_rest = 0.5; const double invMass1 = 1.0 / mc1->mass; const double invMass2 = 1.0 / mc2->mass; const vector3d hitPos1 = c->pos - poc1->pos; const vector3d hitPos2 = c->pos - poc2->pos; const vector3d hitVel1 = dc1->vel + dc1->angVel.Cross(hitPos1); const vector3d hitVel2 = dc2->vel + dc2->angVel.Cross(hitPos2); const double relVel = (hitVel1 - hitVel2).Dot(c->normal); // moving away so no collision if (relVel > 0) return; const double invAngInert1 = 1.0 / dc1->angInertia; const double invAngInert2 = 1.0 / dc2->angInertia; const double numerator = -(1.0 + coeff_rest) * relVel; const double term1 = invMass1; const double term2 = invMass2; const double term3 = c->normal.Dot((hitPos1.Cross(c->normal) * invAngInert1).Cross(hitPos1)); const double term4 = c->normal.Dot((hitPos2.Cross(c->normal) * invAngInert2).Cross(hitPos2)); const double j = numerator / (term1 + term2 + term3 + term4); const vector3d force = j * c->normal; dc1->vel += force * invMass1; dc1->angVel += hitPos1.Cross(force) * invAngInert1; dc2->vel -= force * invMass2; dc2->angVel -= hitPos2.Cross(force) * invAngInert2; }
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 hitCallback(CollisionContact *c) { //printf("OUCH! %x (depth %f)\n", SDL_GetTicks(), c->depth); Object *po1 = static_cast<Object*>(c->userData1); Object *po2 = static_cast<Object*>(c->userData2); const bool po1_isDynBody = po1->IsType(Object::DYNAMICBODY); const bool po2_isDynBody = po2->IsType(Object::DYNAMICBODY); // collision response assert(po1_isDynBody || po2_isDynBody); if (po1_isDynBody && po2_isDynBody) { DynamicBody *b1 = static_cast<DynamicBody*>(po1); DynamicBody *b2 = static_cast<DynamicBody*>(po2); const vector3d linVel1 = b1->GetVelocity(); const vector3d linVel2 = b2->GetVelocity(); const vector3d angVel1 = b1->GetAngVelocity(); const vector3d angVel2 = b2->GetAngVelocity(); const double coeff_rest = 0.5; // step back // mover->UndoTimestep(); const double invMass1 = 1.0 / b1->GetMass(); const double invMass2 = 1.0 / b2->GetMass(); const vector3d hitPos1 = c->pos - b1->GetPosition(); const vector3d hitPos2 = c->pos - b2->GetPosition(); const vector3d hitVel1 = linVel1 + angVel1.Cross(hitPos1); const vector3d hitVel2 = linVel2 + angVel2.Cross(hitPos2); const double relVel = (hitVel1 - hitVel2).Dot(c->normal); // moving away so no collision if (relVel > 0) return; if (!OnCollision(po1, po2, c, -relVel)) return; const double invAngInert1 = 1.0 / b1->GetAngularInertia(); const double invAngInert2 = 1.0 / b2->GetAngularInertia(); const double numerator = -(1.0 + coeff_rest) * relVel; const double term1 = invMass1; const double term2 = invMass2; const double term3 = c->normal.Dot((hitPos1.Cross(c->normal)*invAngInert1).Cross(hitPos1)); const double term4 = c->normal.Dot((hitPos2.Cross(c->normal)*invAngInert2).Cross(hitPos2)); const double j = numerator / (term1 + term2 + term3 + term4); const vector3d force = j * c->normal; b1->SetVelocity(linVel1 + force*invMass1); b1->SetAngVelocity(angVel1 + hitPos1.Cross(force)*invAngInert1); b2->SetVelocity(linVel2 - force*invMass2); b2->SetAngVelocity(angVel2 - hitPos2.Cross(force)*invAngInert2); } else { // one body is static vector3d hitNormal; DynamicBody *mover; if (po1_isDynBody) { mover = static_cast<DynamicBody*>(po1); hitNormal = c->normal; } else { mover = static_cast<DynamicBody*>(po2); hitNormal = -c->normal; } const double coeff_rest = 0.5; const vector3d linVel1 = mover->GetVelocity(); const vector3d angVel1 = mover->GetAngVelocity(); // step back // mover->UndoTimestep(); const double invMass1 = 1.0 / mover->GetMass(); const vector3d hitPos1 = c->pos - mover->GetPosition(); const vector3d hitVel1 = linVel1 + angVel1.Cross(hitPos1); const double relVel = hitVel1.Dot(c->normal); // moving away so no collision if (relVel > 0 && !c->geomFlag) return; if (!OnCollision(po1, po2, c, -relVel)) return; const double invAngInert = 1.0 / mover->GetAngularInertia(); const double numerator = -(1.0 + coeff_rest) * relVel; const double term1 = invMass1; const double term3 = c->normal.Dot((hitPos1.Cross(c->normal)*invAngInert).Cross(hitPos1)); const double j = numerator / (term1 + term3); const vector3d force = j * c->normal; mover->SetVelocity(linVel1 + force*invMass1); mover->SetAngVelocity(angVel1 + hitPos1.Cross(force)*invAngInert); } }
{ GeoSphere::UpdateAllGeoSpheres(); GasGiant::UpdateAllGasGiants(); } //static void BaseSphere::OnChangeDetailLevel() { GeoSphere::OnChangeDetailLevel(); } void BaseSphere::DrawAtmosphereSurface(Graphics::Renderer *renderer, const matrix4x4d &modelView, const vector3d &campos, float rad, Graphics::RenderState *rs, RefCountedPtr<Graphics::Material> mat) { PROFILE_SCOPED() 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); if(!m_atmos) m_atmos.reset( new Drawables::Sphere3D(renderer, mat, rs, 4, 1.0f, ATTRIB_POSITION)); m_atmos->Draw(renderer); renderer->GetStats().AddToStatCount(Graphics::Stats::STAT_ATMOSPHERES, 1); }
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); }
static void raytraceCollMesh(vector3d camPos, vector3d camera_up, vector3d camera_forward, CollisionSpace *space) { memset(wank, 0, sizeof(float)*TEXSIZE*TEXSIZE); vector3d toPoint, xMov, yMov; vector3d topLeft, topRight, botRight, cross; topLeft = topRight = botRight = camera_forward * camera_zoom; cross = camera_forward.Cross(camera_up) * aspectRatio; topLeft = topLeft + camera_up - cross; topRight = topRight + camera_up + cross; botRight = botRight - camera_up + cross; xMov = topRight - topLeft; yMov = botRight - topRight; float xstep = 1.0f / TEXSIZE; float ystep = 1.0f / TEXSIZE; float xpos, ypos; ypos = 0.0f; GeomTree::stats_rayTriIntersections = 0; Uint32 t = SDL_GetTicks(); for (int y=0; y<TEXSIZE; y++, ypos += ystep) { xpos = 0.0f; for (int x=0; x<TEXSIZE; x++, xpos += xstep) { toPoint = (topLeft + (xMov * xpos) + (yMov * ypos)).Normalized(); CollisionContact c; space->TraceRay(camPos, toPoint, 1000000.0f, &c); if (c.triIdx != -1) { wank[x][y] = 100.0/(10*c.dist); } else { wank[x][y] = 0; } } } printf("%.3f million rays/sec, %.2f tri isect tests per ray\n", (TEXSIZE*TEXSIZE)/(1000.0*(SDL_GetTicks()-t)), GeomTree::stats_rayTriIntersections/(float)(TEXSIZE*TEXSIZE)); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, mytexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXSIZE, TEXSIZE, 0, GL_LUMINANCE, GL_FLOAT, wank); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 1, 0, 1, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); //glActiveTexture(GL_TEXTURE0); glDisable(GL_LIGHTING); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glBegin(GL_TRIANGLE_FAN); glTexCoord2i(0,1); glVertex3f(1,1,0); glTexCoord2i(0,0); glVertex3f(0,1,0); glTexCoord2i(1,0); glVertex3f(0,0,0); glTexCoord2i(1,1); glVertex3f(1,0,0); glEnd(); glDisable(GL_TEXTURE_2D); }