ZString GetString(int indent, const Orientation& orient) { return "Orientation(" + GetString(indent, orient.GetUp()) + ", " + GetString(indent, orient.GetForward()) + ")"; }
void CprobeIGC::Update(Time now) { if (now >= m_timeExpire) GetMyMission()->GetIgcSite()->KillProbeEvent(this); else { { float dt = m_probeType->GetRipcordDelay(); if (dt >= 0.0f) { Time timeActivate = m_time0 + dt; if ((GetMyLastUpdate() < timeActivate) && (now >= timeActivate)) { GetMyMission()->GetIgcSite()->ActivateTeleportProbe(this); } } } if (m_projectileType) { if (m_nextFire < now) { IclusterIGC* pcluster = GetCluster(); assert (pcluster); //We'll be able to take a shot float lifespan = GetProjectileLifespan(); IsideIGC* pside = GetSide(); const Vector& myPosition = GetPosition(); float speed = m_projectileType->GetSpeed(); if (m_ammo != 0) speed *= GetSide()->GetGlobalAttributeSet().GetAttribute(c_gaSpeedAmmo); float accuracy = GetAccuracy(); float dtimeBurst = GetDtBurst(); float dispersion = m_probeType->GetDispersion(); Time lastUpdate = GetMyLastUpdate(); if (m_nextFire < lastUpdate) m_nextFire = lastUpdate; assert (m_nextFire <= now); TmodelIGC<IprobeIGC>::Update(now); float dtUpdate = m_nextFire - lastUpdate; //If we have a target ... find the closest enemy ship who is a valid target ExpendableAbilityBitMask eabm = m_probeType->GetCapabilities(); float distance2Min = speed * lifespan / 1.2f; distance2Min *= distance2Min; Vector directionMin; ImodelIGC* pmodelTarget = NULL; if (eabm & c_eabmShootOnlyTarget) { if (m_target && (m_target->GetCluster() == pcluster)) { ObjectType type = m_target->GetObjectType(); ValidTarget((type == OT_ship) ? ((IshipIGC*)(ImodelIGC*)m_target)->GetSourceShip() : m_target, pside, myPosition, dtUpdate, accuracy, speed, lifespan, type, &pmodelTarget, &distance2Min, &directionMin); } } else { if (eabm & c_eabmShootShips) { //Threats to stations get highest priority GetTarget((const ModelListIGC*)(pcluster->GetShips()), pside, myPosition, dtUpdate, accuracy, speed, lifespan, OT_ship, &pmodelTarget, &distance2Min, &directionMin); } if (eabm & c_eabmShootMissiles) { GetTarget((const ModelListIGC*)(pcluster->GetMissiles()), pside, myPosition, dtUpdate, accuracy, speed, lifespan, OT_missile, &pmodelTarget, &distance2Min, &directionMin); } if (eabm & c_eabmShootStations) { GetTarget((const ModelListIGC*)(pcluster->GetStations()), pside, myPosition, dtUpdate, accuracy, speed, lifespan, OT_station, &pmodelTarget, &distance2Min, &directionMin); } } if (pmodelTarget) { if (m_launcher && (m_launcher->GetMission() != GetMyMission())) m_launcher = NULL; //It is going to shoot ... make it visible to everyone in the sector if (!m_bSeenByAll) { m_bSeenByAll = true; for (SideLinkIGC* psl = m_pMission->GetSides()->first(); (psl != NULL); psl = psl->next()) { IsideIGC* psideOther = psl->data(); if (!SeenBySide(psideOther)) { //Does this side have any scanners in the sector? ClusterSite* pcs = pcluster->GetClusterSite(); const ScannerListIGC* psl = pcs->GetScanners(psideOther->GetObjectID()); if ((psl->n() != 0) || (m_pMission->GetMissionParams()->bAllowAlliedViz && psideOther->AlliedSides(psideOther,pside))) //ALLY 7/3/09 VISIBILITY 7/11/09 imago SetSideVisibility(psideOther, true); else m_bSeenByAll = false; } } } //We have a target ... fire along directionMin (modulo dispersion) Orientation o = GetOrientation(); o.TurnTo(directionMin); SetOrientation(o); Vector position = myPosition + m_probeType->GetEmissionPt() * o; DataProjectileIGC dataProjectile; dataProjectile.projectileTypeID = m_projectileType->GetObjectID(); short nShots = 0; do { //Permute the "forward" direction slightly by a random amount dataProjectile.forward = directionMin; if (dispersion != 0.0f) { float r = random(0.0f, dispersion); float a = random(0.0f, 2.0f * pi); dataProjectile.forward += (r * cos(a)) * o.GetRight(); dataProjectile.forward += (r * sin(a)) * o.GetUp(); dataProjectile.forward.SetNormalize(); } //We never move, so skip all the velocity calculations dataProjectile.velocity = speed * dataProjectile.forward; dataProjectile.lifespan = lifespan; IprojectileIGC* p = (IprojectileIGC*)(m_pMission->CreateObject(m_nextFire, OT_projectile, &dataProjectile, sizeof(dataProjectile))); assert (p); { p->SetLauncher(m_launcher ? ((ImodelIGC*)m_launcher) : ((ImodelIGC*)this)); p->SetPosition(position); p->SetCluster(pcluster); p->Release(); } nShots++; m_nextFire += dtimeBurst; } while (m_nextFire < now); if (m_ammo > 0) { m_ammo -= nShots; if (m_ammo <= 0) { m_ammo = 0; GetMyMission()->GetIgcSite()->KillProbeEvent(this); } } } else { //No shots this cycle m_nextFire = now; } } } TmodelIGC<IprobeIGC>::Update(now); } }
void ShadowSystem::ProcessEntity(ECS::Entity* p_entity) { Transform* transform = m_transforms.Get(p_entity); Shadowcaster* shadowcaster = m_shadowcasters.Get(p_entity); Render::Shadowcaster sc; Orientation tOr = transform->m_orientation; tOr.Yaw(180.0f); glm::mat4 tempWorldMatrix; tempWorldMatrix = glm::translate(glm::mat4(1.0f), transform->m_position); tempWorldMatrix = glm::rotate(tempWorldMatrix, tOr.GetAngle(), tOr.GetAxis()); tempWorldMatrix = glm::scale(tempWorldMatrix, transform->m_scale); glm::mat4 lightSpace = glm::inverse(tempWorldMatrix); m_maxWorldX = -99999; m_minWorldX = 99999; m_maxWorldY = -99999; m_minWorldY = 99999; m_maxWorldZ = -99999; m_minWorldZ = 99999; for(int i = 0; i < 8; i++) { glm::vec4 cornerInLightSpace = lightSpace * glm::vec4(worldCorners[i], 1.0f); if(cornerInLightSpace.x < m_minWorldX) { m_minWorldX = cornerInLightSpace.x; } if(cornerInLightSpace.x > m_maxWorldX) { m_maxWorldX = cornerInLightSpace.x; } if(cornerInLightSpace.y < m_minWorldY) { m_minWorldY = cornerInLightSpace.y; } if(cornerInLightSpace.y > m_maxWorldY) { m_maxWorldY = cornerInLightSpace.y; } if(cornerInLightSpace.z < m_minWorldZ) { m_minWorldZ = cornerInLightSpace.z; } if(cornerInLightSpace.z > m_maxWorldZ) { m_maxWorldZ = cornerInLightSpace.z; } } glm::mat4 lazyOrthoAroundMap = glm::ortho(m_minWorldX, m_maxWorldX, m_minWorldY, m_maxWorldY, -m_maxWorldZ, -m_minWorldZ); // Get the eye camera. ECS::Entity* cameraEntity = m_world->GetTagManager()->GetEntityByTag("Camera"); RootForce::Camera* camera = m_world->GetEntityManager()->GetComponent<RootForce::Camera>(cameraEntity); Frustum frustum = camera->m_frustum; glm::vec4 frustumCorners[8]; frustumCorners[0] = glm::vec4(frustum.ntl, 1.0f); frustumCorners[1] = glm::vec4(frustum.ntr, 1.0f); frustumCorners[2] = glm::vec4(frustum.nbl, 1.0f); frustumCorners[3] = glm::vec4(frustum.nbr, 1.0f); frustumCorners[4] = glm::vec4(frustum.ftl, 1.0f); frustumCorners[5] = glm::vec4(frustum.ftr, 1.0f); frustumCorners[6] = glm::vec4(frustum.fbl, 1.0f); frustumCorners[7] = glm::vec4(frustum.fbr, 1.0f); // Convert camera frustrum to view space. for(int i = 0; i < 8; i++) { frustumCorners[i] = camera->m_viewMatrix * frustumCorners[i]; } // Calculate directions. glm::vec3 directions[4]; for(int i = 0; i < 4; i++) { directions[i].x = glm::normalize(frustumCorners[i+4].x - frustumCorners[i].x); directions[i].y = glm::normalize(frustumCorners[i+4].y - frustumCorners[i].y); directions[i].z = glm::normalize(frustumCorners[i+4].z - frustumCorners[i].z); } static glm::vec4 localOBB[8] = { glm::vec4(-1.0f, -1.0f, -1.0f, 1.0f), glm::vec4(1.0f, -1.0f, -1.0f, 1.0f), glm::vec4(1.0f, 1.0f, -1.0f, 1.0f), glm::vec4(1.0f, 1.0f, 1.0f, 1.0f), glm::vec4(-1.0f, 1.0f, -1.0f, 1.0f), glm::vec4(-1.0f, 1.0f, 1.0f, 1.0f), glm::vec4(-1.0f, -1.0f, 1.0f, 1.0f), glm::vec4(1.0f, -1.0f, 1.0f, 1.0f) }; if(RENDER_SHADOW_CASCADES >= 4) { // Define near/far planes for the sub frustrums. float _near[4]; _near[0] = camera->m_frustum.m_near; _near[1] = 8.0f; //Daniel's 2k-values: 15, 60, 200 _near[2] = 40.0f; _near[3] = 150.0f; float _far[4]; _far[0] = _near[1]; _far[1] = _near[2]; _far[2] = _near[3]; _far[3] = camera->m_frustum.m_far; // Create cascades. for(int i = 0; i < RENDER_SHADOW_CASCADES; i++) { AABB boundingbox; for(int p = 0; p < 4; p++) { glm::vec3 nearCorner; nearCorner = glm::swizzle<glm::X, glm::Y, glm::Z>(frustumCorners[p]); boundingbox.Expand(nearCorner + directions[p] * _near[i]); boundingbox.Expand(nearCorner + directions[p] * _far[i]); } glm::vec3 center = boundingbox.GetCenter(); glm::vec3 centerInWorldSpace = glm::swizzle<glm::X, glm::Y, glm::Z>(glm::inverse(camera->m_viewMatrix) * glm::vec4(center, 1.0f)); glm::vec4 centerInViewSpace = lightSpace * glm::vec4(centerInWorldSpace, 1.0f); float nearPlane = 1.0f; float lookAtDistance = glm::length(centerInViewSpace - 2000.0f) + nearPlane; float radius = glm::length(center - glm::vec3(boundingbox.m_maxX, boundingbox.m_maxY, boundingbox.m_maxZ)); float farPlane = lookAtDistance + radius; sc.m_projectionMatrices[i] = glm::ortho(-radius, radius, -radius, radius, nearPlane, farPlane); sc.m_viewMatrices[i] = glm::lookAt(centerInWorldSpace + tOr.GetFront() * lookAtDistance, centerInWorldSpace - tOr.GetFront() * lookAtDistance, tOr.GetUp()); sc.m_viewProjections[i] = sc.m_projectionMatrices[i] * sc.m_viewMatrices[i]; } sc.m_projectionMatrices[RENDER_SHADOW_CASCADES-1] = OrthoProjectionFromFrustum(&camera->m_frustum, lightSpace); sc.m_viewMatrices[RENDER_SHADOW_CASCADES-1] = lightSpace; sc.m_viewProjections[RENDER_SHADOW_CASCADES-1] = sc.m_projectionMatrices[RENDER_SHADOW_CASCADES-1] * sc.m_viewMatrices[RENDER_SHADOW_CASCADES-1]; } else { sc.m_projectionMatrices[RENDER_SHADOW_CASCADES-1] = lazyOrthoAroundMap; sc.m_viewMatrices[RENDER_SHADOW_CASCADES-1] = lightSpace; sc.m_viewProjections[RENDER_SHADOW_CASCADES-1] = sc.m_projectionMatrices[RENDER_SHADOW_CASCADES-1] * sc.m_viewMatrices[RENDER_SHADOW_CASCADES-1]; } g_engineContext.m_renderer->AddShadowcaster(sc, (int)shadowcaster->m_directionalLightSlot); }
void CFSShip::HitWarp(IwarpIGC * pwarp) { //Ignore jumps that happen too closely together if (m_warpState == warpReady) { // Andon - Added check for aleph mass limits if (m_pShip->GetMass() <= pwarp->MassLimit() || !IsPlayer() && pwarp->MassLimit() > 0 || pwarp->MassLimit() < 0) { if (IsPlayer()) { m_warpState = warpNoUpdate; } IwarpIGC * pwarpDest = pwarp->GetDestination(); assert (pwarpDest); IclusterIGC * pclusterDest = pwarpDest->GetCluster(); ShipStatusWarped(pwarp); Orientation alephOrientation = pwarpDest->GetOrientation(); const Vector& v = m_pShip->GetVelocity(); float speed2 = v.LengthSquared(); float speed = float(sqrt(speed2)); if (speed2 > 0) { float error; { //How close is the ship coming to the center of the warp? Vector dp = pwarp->GetPosition() - m_pShip->GetPosition(); float t = (dp * v) / speed2; float d = (dp - t * v).LengthSquared(); float r = pwarp->GetRadius(); error = (d / (r*r)) + 0.125f; //Error ranges from 0.125 to 1.125 // yp: to prevent 'spin of death' in massive ships. // This works and is explained in that the more massive the ship the less effect going through the aleph should have // on its rotational velocity. The massive amount of inertia should decrease changes in rotational velocity. if(m_pShip->GetMass() > 300.0f) { error = error * (300.0f / m_pShip->GetMass()); // the greater the mass is above 750 the less error will be applied. } // yp end } alephOrientation.Pitch(random(-error, error)); alephOrientation.Yaw(random(-error, error)); m_pShip->SetCurrentTurnRate(c_axisRoll, m_pShip->GetCurrentTurnRate(c_axisRoll) + random(pi * 0.5f * error, pi * 1.5f * error)); //Must be less than 2.0 * pi } m_pShip->SetOrientation(alephOrientation); const Vector& backward = alephOrientation.GetBackward(); speed = -(speed + pwarp->GetMission()->GetFloatConstant(c_fcidExitWarpSpeed)); m_pShip->SetVelocity(backward * speed); m_pShip->SetPosition(pwarpDest->GetPosition() + (alephOrientation.GetUp() * random(2.0f, 5.0f)) + (alephOrientation.GetRight() * random(2.0f, 5.0f)) - (m_pShip->GetRadius() + 5.0f) * backward); GetIGCShip()->SetCluster(pclusterDest); } } }