fixed CTerrain::GetExactGroundLevelFixed(fixed x, fixed z) const { // Clamp to size-2 so we can use the tiles (xi,zi)-(xi+1,zi+1) const ssize_t xi = clamp((ssize_t)(x / (int)TERRAIN_TILE_SIZE).ToInt_RoundToZero(), (ssize_t)0, m_MapSize-2); const ssize_t zi = clamp((ssize_t)(z / (int)TERRAIN_TILE_SIZE).ToInt_RoundToZero(), (ssize_t)0, m_MapSize-2); const fixed one = fixed::FromInt(1); const fixed xf = clamp((x / (int)TERRAIN_TILE_SIZE) - fixed::FromInt(xi), fixed::Zero(), one); const fixed zf = clamp((z / (int)TERRAIN_TILE_SIZE) - fixed::FromInt(zi), fixed::Zero(), one); u16 h00 = m_Heightmap[zi*m_MapSize + xi]; u16 h01 = m_Heightmap[(zi+1)*m_MapSize + xi]; u16 h10 = m_Heightmap[zi*m_MapSize + (xi+1)]; u16 h11 = m_Heightmap[(zi+1)*m_MapSize + (xi+1)]; // Intermediate scaling of xf, so we don't overflow in the multiplications below // (h00 <= 65535, xf <= 1, max fixed is < 32768; divide by 2 here so xf1*h00 <= 32767.5) const fixed xf0 = xf / 2; const fixed xf1 = (one - xf) / 2; // Linearly interpolate return ((one - zf).Multiply(xf1 * h00 + xf0 * h10) + zf.Multiply(xf1 * h01 + xf0 * h11)) / (int)(HEIGHT_UNITS_PER_METRE / 2); // TODO: This should probably be more like GetExactGroundLevel() // in handling triangulation properly }
float GetConstructionProgressOffset(const CVector3D& pos) { if (m_ConstructionProgress.IsZero()) return 0.0f; CmpPtr<ICmpVisual> cmpVisual(GetEntityHandle()); if (!cmpVisual) return 0.0f; // We use selection boxes to calculate the model size, since the model could be offset // TODO: this annoyingly shows decals, would be nice to hide them CBoundingBoxOriented bounds = cmpVisual->GetSelectionBox(); if (bounds.IsEmpty()) return 0.0f; float dy = 2.0f * bounds.m_HalfSizes.Y; // If this is a floating unit, we want it to start all the way under the terrain, // so find the difference between its current position and the terrain CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity()); if (cmpTerrain && (m_Floating || m_ActorFloating)) { float ground = cmpTerrain->GetExactGroundLevel(pos.X, pos.Z); dy += std::max(0.f, pos.Y - ground); } return (m_ConstructionProgress.ToFloat() - 1.0f) * dy; }
void Rotate(const Angle alpha) { const auto sc = alpha.SinCos(); const fixed sin = sc.first, cos = sc.second; #ifdef FIXED_MATH long s = sin.as_glfixed(); long c = cos.as_glfixed(); #else long s = sin * (1<<16); long c = cos * (1<<16); #endif Rotatex(s, c); }
void Scale(const fixed &factor) { #ifdef FIXED_MATH Scalex(factor.as_glfixed_scale()); #else Scalex(factor * (1LL<<32)); #endif }
virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize) { Init(paramNode); u32 oldSeed = GetActorSeed(); SerializeCommon(deserialize); // If we serialized a different seed, reload actor if (oldSeed != GetActorSeed()) ReloadActor(); fixed repeattime = m_AnimSyncRepeatTime; // save because SelectAnimation overwrites it if (m_AnimRunThreshold.IsZero()) SelectAnimation(m_AnimName, m_AnimOnce, m_AnimSpeed, m_SoundGroup); else SelectMovementAnimation(m_AnimRunThreshold); SetAnimationSyncRepeat(repeattime); if (m_Unit) { CmpPtr<ICmpOwnership> cmpOwnership(GetSimContext(), GetEntityId()); if (cmpOwnership) m_Unit->GetModel().SetPlayerID(cmpOwnership->GetOwner()); } }
const Color Faction::AdjustedColour(fixed population, bool inRange) { Color result; result = population == 0 ? BAD_FACTION_COLOUR : colour; result.a = population > 0 ? FACTION_BASE_ALPHA + (M_E + (logf(population.ToFloat() / 1.25))) / ((2 * M_E) + FACTION_BASE_ALPHA) : FACTION_BASE_ALPHA; result.a = inRange ? 1.f : result.a; return result; }
virtual void SetAnimationSyncOffset(fixed actiontime) { if (m_Unit) { if (m_Unit->GetAnimation()) m_Unit->GetAnimation()->SetAnimationSyncOffset(actiontime.ToFloat()); } }
virtual void SetAnimationSyncRepeat(fixed repeattime) { m_AnimSyncRepeatTime = repeattime; if (m_Unit) { if (m_Unit->GetAnimation()) m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat()); } }
virtual void Hotload(const VfsPath& name) { if (!m_Unit) return; if (name != m_ActorName) return; std::set<CStr> selections; CUnit* newUnit = GetSimContext().GetUnitManager().CreateUnit(m_ActorName, GetActorSeed(), selections); if (!newUnit) return; // Save some data from the old unit CColor shading = m_Unit->GetModel().GetShadingColor(); player_id_t playerID = m_Unit->GetModel().GetPlayerID(); // Replace with the new unit GetSimContext().GetUnitManager().DeleteUnit(m_Unit); m_Unit = newUnit; m_Unit->SetID(GetEntityId()); m_Unit->SetEntitySelection(m_AnimName); if (m_Unit->GetAnimation()) m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str()); // We'll lose the exact synchronisation but we should at least make sure it's going at the correct rate if (!m_AnimSyncRepeatTime.IsZero()) if (m_Unit->GetAnimation()) m_Unit->GetAnimation()->SetAnimationSyncRepeat(m_AnimSyncRepeatTime.ToFloat()); m_Unit->GetModel().SetShadingColor(shading); m_Unit->GetModel().SetPlayerID(playerID); // TODO: should copy/reset silhouette flags }
virtual void SelectAnimation(std::string name, bool once, fixed speed, std::wstring soundgroup) { m_AnimRunThreshold = fixed::Zero(); m_AnimName = name; m_AnimOnce = once; m_AnimSpeed = speed; m_SoundGroup = soundgroup; m_AnimDesync = fixed::FromInt(1)/20; // TODO: make this an argument m_AnimSyncRepeatTime = fixed::Zero(); if (m_Unit) { m_Unit->SetEntitySelection(m_AnimName); if (m_Unit->GetAnimation()) m_Unit->GetAnimation()->SetAnimationState(m_AnimName, m_AnimOnce, m_AnimSpeed.ToFloat(), m_AnimDesync.ToFloat(), m_SoundGroup.c_str()); } }
fixed tanx(fixed x) { return x.tan(); }
fixed cosx(fixed x) { return x.cos(); }
fixed sinx(fixed x) { return x.sin(); }
fixed ceilx(fixed fixedVal) { return fixedVal.ceil(); }
fixed floorx(fixed fixedVal) { return fixedVal.floor(); }
fixed logx(fixed fixedVal) { return fixedVal.log(); }
fixed expx(fixed fixedVal) { return fixedVal.exp(); }
template <> void XMLWriter_File::ElementAttribute<fixed>(const char* name, const fixed& value, bool newelement) { ElementAttribute(name, value.ToString().c_str(), newelement); }
void IDeserializer::NumberFixed_Unbounded(const char* name, fixed& out) { int32_t n; NumberI32_Unbounded(name, n); out.SetInternalValue(n); }
fixed operator*(fixed a, long b) { return a.multiply(b); }
void CDebugSerializer::PutNumber(const char* name, fixed value) { m_Stream << INDENT << name << ": " << value.ToString() << "\n"; }
fixed sqrtx(fixed fixedVal) { return fixedVal.sqrt(); }
fixed log10x(fixed fixedVal) { return fixedVal.log10(); }
template<> void ScriptInterface::ToJSVal<fixed>(JSContext* UNUSED(cx), JS::MutableHandleValue ret, const fixed& val) { ret.set(JS::NumberValue(val.ToDouble())); }
fixed powx(fixed fixedVal, fixed fixedPower) { return fixedVal.pow(fixedPower); }