// Liang-Barsky line clipping. Return true if the line isn't completely clipped. static bool ClipLine(ref Vector3 start, ref Vector3 end, MyMwcVector3Int min, MyMwcVector3Int max) { Vector3 dir = end - start; if (MyMwcUtils.IsZero(dir)) { return(IsPointInside(start, min, max)); } float tE = 0, tL = 1; if (IntersectionT(min.X - start.X, dir.X, ref tE, ref tL) && IntersectionT(start.X - max.X - 1, -dir.X, ref tE, ref tL) && IntersectionT(min.Y - start.Y, dir.Y, ref tE, ref tL) && IntersectionT(start.Y - max.Y - 1, -dir.Y, ref tE, ref tL) && IntersectionT(min.Z - start.Z, dir.Z, ref tE, ref tL) && IntersectionT(start.Z - max.Z - 1, -dir.Z, ref tE, ref tL)) { if (tL < 1) { end = start + tL * dir; } if (tE > 0) { start += tE * dir; } return(true); } return(false); }
public void AddShake(float shakePower) { if (MyFakes.DISABLE_CAMERA_HEADSHAKE) { return; } if (MyMwcUtils.IsZero(shakePower)) { return; } if (MyMwcUtils.IsZero(m_MaxShake)) { return; } float pow = (shakePower / m_MaxShake); //MyMwcLog.WriteLine(pow.ToString()); if (m_CurrentShakePosPower < pow) { m_CurrentShakePosPower = pow; } if (m_CurrentShakeDirPower < pow * m_DirReduction) { m_CurrentShakeDirPower = pow * m_DirReduction; } m_ShakePos = new Vector3(m_CurrentShakePosPower * m_MaxShakePos, m_CurrentShakePosPower * m_MaxShakePos, m_CurrentShakePosPower * m_MaxShakePos); m_ShakeDir = new Vector3(m_CurrentShakeDirPower * m_MaxShakeDir, 0.0f, m_CurrentShakeDirPower * m_MaxShakeDir); m_Shake = true; }
static bool IntersectionT(float n, float d, ref float tE, ref float tL) { if (MyMwcUtils.IsZero(d)) { return(n <= 0); } float t = n / d; if (d > 0) { if (t > tL) { return(false); } if (t > tE) { tE = t; } } else { if (t < tE) { return(false); } if (t < tL) { tL = t; } } return(true); }
/// <summary> /// Applies external force to the physics object. /// </summary> /// <param name="type">The type.</param> /// <param name="force">The force.</param> /// <param name="position">The position.</param> /// <param name="torque">The torque.</param> public void AddForce(MyPhysicsForceType type, Vector3?force, Vector3?position, Vector3?torque) { MyUtils.AssertIsValid(force); MyUtils.AssertIsValid(position); MyUtils.AssertIsValid(torque); switch (type) { case MyPhysicsForceType.ADD_BODY_FORCE_AND_BODY_TORQUE: { Matrix tempM = rigidBody.Matrix; tempM.Translation = Vector3.Zero; if (force != null && !MyMwcUtils.IsZero(force.Value)) { Vector3 tmpForce = Vector3.Transform(force.Value, tempM); this.rigidBody.ApplyForce(tmpForce); } if (torque != null && !MyMwcUtils.IsZero(torque.Value)) { Vector3 tmpTorque = Vector3.Transform(torque.Value, tempM); this.rigidBody.ApplyTorque(tmpTorque); } } break; case MyPhysicsForceType.APPLY_WORLD_IMPULSE_AND_WORLD_ANGULAR_IMPULSE: { if (force.HasValue && position.HasValue) { this.rigidBody.ApplyImpulse(force.Value, position.Value); } if (torque.HasValue) { this.rigidBody.ApplyTorque(torque.Value); } } break; default: { Debug.Fail("Unhandled enum!"); } break; } }
public static float AngleBetween(Vector3 a, Vector3 b) { var dotProd = Vector3.Dot(a, b); var lenProd = a.Length() * b.Length(); var divOperation = dotProd / lenProd; if (MyMwcUtils.IsZero(1.0f - divOperation)) { return(0); } else { return((float)(Math.Acos(divOperation))); } }
private void SetAngularVelocity(Vector3 vel) { MinerWars.AppCode.Game.Utils.MyUtils.AssertIsValid(vel); if (ReadFlag(RigidBodyFlag.RBF_KINEMATIC) || ReadFlag(RigidBodyFlag.RBF_RBO_STATIC)) { return; } if (MyMwcUtils.IsZero(m_AngularVelocity - vel)) { return; } m_AngularVelocity = vel; WakeUp(); }
// Generate explosion particles. These will be smoke, explosion and some polyline particles. void GenerateExplosionParticles(MyParticleEffectsIDEnum newParticlesType, BoundingSphere explosionSphere, float particleScale) { Vector3 dirToCamera = MyCamera.Position - explosionSphere.Center; if (MyMwcUtils.IsZero(dirToCamera)) { dirToCamera = MyCamera.ForwardVector; } else { dirToCamera = MyMwcUtils.Normalize(dirToCamera); } // Move explosion particles in the direction of camera, so we won't see billboards intersecting the large ship BoundingSphere tempExplosionSphere = m_explosionSphere; tempExplosionSphere.Center = m_explosionSphere.Center + dirToCamera * 0.9f; MyParticleEffect explosionEffect = MyParticlesManager.CreateParticleEffect((int)newParticlesType); explosionEffect.WorldMatrix = Matrix.CreateTranslation(tempExplosionSphere.Center); explosionEffect.UserRadiusMultiplier = tempExplosionSphere.Radius; explosionEffect.UserScale = particleScale; }
public static void Calculate(List <MyMwcVector3Int> result, float gridSize, Vector3 lineStart, Vector3 lineEnd, MyMwcVector3Int min, MyMwcVector3Int max) { var dir = lineEnd - lineStart; MyCommonDebugUtils.AssertDebug(MyUtils.IsValid(dir)); // handle start==end Vector3 start = lineStart / gridSize; if (MyMwcUtils.IsZero(dir)) { if (IsPointInside(start, min, max)) { result.Add(GetGridPoint(ref start, min, max)); } return; } // start/end in grid coordinates: clip them to the bounding box, return if no intersection Vector3 end = lineEnd / gridSize; if (ClipLine(ref start, ref end, min, max) == false) { return; } // reflect coordinates so that dir is always positive Vector3 sign = Sign(dir); MyMwcVector3Int signInt = SignInt(dir); // current/final grid position MyMwcVector3Int cur = GetGridPoint(ref start, min, max) * signInt; MyMwcVector3Int final = GetGridPoint(ref end, min, max) * signInt; dir *= sign; start *= sign; // dx = increase of t when we increase x by 1 // nextX = t of the next point on the line with x whole float dx = 1 / dir.X, nextX = dx * ((float)Math.Floor(start.X + 1) - start.X); float dy = 1 / dir.Y, nextY = dy * ((float)Math.Floor(start.Y + 1) - start.Y); float dz = 1 / dir.Z, nextZ = dz * ((float)Math.Floor(start.Z + 1) - start.Z); // 3D DDA while (true) { result.Add(cur * signInt); if (nextX < nextZ) { if (nextX < nextY) { nextX += dx; if (++cur.X > final.X) { break; } } else { nextY += dy; if (++cur.Y > final.Y) { break; } } } else { if (nextZ < nextY) { nextZ += dz; if (++cur.Z > final.Z) { break; } } else { nextY += dy; if (++cur.Y > final.Y) { break; } } } } }
// Update position, check collisions, etc. and draw if particle still lives. // Return false if particle dies/timeouts in this tick. public bool Draw(MyBillboard billboard) { MyTransparentGeometry.StartParticleProfilingBlock("Distance calculation"); // This time is scaled according to planned lifespan of the particle // Distance for sorting Vector3 campos = MyCamera.Position; Vector3.DistanceSquared(ref campos, ref m_actualPosition, out billboard.DistanceSquared); MyTransparentGeometry.EndParticleProfilingBlock(); // If distance to camera is really small don't draw it. if (billboard.DistanceSquared <= 1) { return(false); } MyTransparentGeometry.StartParticleProfilingBlock("Quad calculation"); MyTransparentGeometry.StartParticleProfilingBlock("actualRadius"); float actualRadius = 1; Radius.GetInterpolatedValue <float>(m_normalizedTime, out actualRadius); MyTransparentGeometry.EndParticleProfilingBlock(); billboard.ContainedBillboards.Clear(); billboard.Near = m_generation.GetEffect().Near; billboard.Lowres = m_generation.GetEffect().LowRes || MyRenderConstants.RenderQualityProfile.LowResParticles; float alpha = 1; if (Type == MyParticleTypeEnum.Point) { MyTransparentGeometry.StartParticleProfilingBlock("GetBillboardQuadRotated"); MyUtils.GetBillboardQuadRotated(billboard, ref m_actualPosition, actualRadius, m_actualAngle); MyTransparentGeometry.EndParticleProfilingBlock(); } else if (Type == MyParticleTypeEnum.Line) { if (MyMwcUtils.IsZero(Velocity.LengthSquared())) { Velocity = MyMwcUtils.GetRandomVector3Normalized(); } MyQuad quad = new MyQuad(); MyPolyLine polyLine = new MyPolyLine(); polyLine.LineDirectionNormalized = MyMwcUtils.Normalize(Velocity); if (m_actualAngle > 0) { polyLine.LineDirectionNormalized = Vector3.TransformNormal(polyLine.LineDirectionNormalized, Matrix.CreateRotationY(MathHelper.ToRadians(m_actualAngle))); } polyLine.Point0 = m_actualPosition; polyLine.Point1.X = m_actualPosition.X + polyLine.LineDirectionNormalized.X * actualRadius; polyLine.Point1.Y = m_actualPosition.Y + polyLine.LineDirectionNormalized.Y * actualRadius; polyLine.Point1.Z = m_actualPosition.Z + polyLine.LineDirectionNormalized.Z * actualRadius; if (m_actualAngle > 0) { //centerize polyLine.Point0.X = polyLine.Point0.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point0.Y = polyLine.Point0.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point0.Z = polyLine.Point0.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; polyLine.Point1.X = polyLine.Point1.X - polyLine.LineDirectionNormalized.X * actualRadius * 0.5f; polyLine.Point1.Y = polyLine.Point1.Y - polyLine.LineDirectionNormalized.Y * actualRadius * 0.5f; polyLine.Point1.Z = polyLine.Point1.Z - polyLine.LineDirectionNormalized.Z * actualRadius * 0.5f; } polyLine.Thickness = Thickness; MyUtils.GetPolyLineQuad(out quad, ref polyLine); if (this.m_generation.AlphaAnisotropic) { float angle = 1 - Math.Abs(Vector3.Dot(MyMwcUtils.Normalize(MyCamera.ForwardVector), polyLine.LineDirectionNormalized)); float alphaCone = (float)Math.Pow(angle, 0.5f); alpha = alphaCone; } billboard.Position0 = quad.Point0; billboard.Position1 = quad.Point1; billboard.Position2 = quad.Point2; billboard.Position3 = quad.Point3; } else if (Type == MyParticleTypeEnum.Trail) { if (Quad.Point0 == Quad.Point2) //not moving particle { return(false); } if (Quad.Point1 == Quad.Point3) //not moving particle was previous one { return(false); } if (Quad.Point0 == Quad.Point3) //not moving particle was previous one { return(false); } billboard.Position0 = Quad.Point0; billboard.Position1 = Quad.Point1; billboard.Position2 = Quad.Point2; billboard.Position3 = Quad.Point3; //if (this.m_generation.AlphaAnisotropic) /* { //Trails are anisotropic by default (nobody wants them to see ugly) * Vector3 lineDir = Vector3.Normalize(Quad.Point1 - Quad.Point0); * float angle = 1 - Math.Abs(Vector3.Dot(MyMwcUtils.Normalize(MyCamera.ForwardVector), lineDir)); * float alphaCone = (float)Math.Pow(angle, 0.3f); * alpha = alphaCone; * }*/ } else { throw new NotSupportedException(Type + " is not supported particle type"); } MyTransparentGeometry.EndParticleProfilingBlock(); MyTransparentGeometry.StartParticleProfilingBlock("Material calculation"); Vector4 color; Color.GetInterpolatedValue <Vector4>(m_normalizedTime, out color); int material1 = (int)MyTransparentMaterialEnum.Test; int material2 = (int)MyTransparentMaterialEnum.Test; float textureBlendRatio = 0; if ((Flags & ParticleFlags.BlendTextures) != 0) { float prevTime, nextTime, difference; Material.GetPreviousValue(m_normalizedTime, out material1, out prevTime); Material.GetNextValue(m_normalizedTime, out material2, out nextTime, out difference); if (prevTime != nextTime) { textureBlendRatio = (m_normalizedTime - prevTime) * difference; } } else { Material.GetInterpolatedValue <int>(m_normalizedTime, out material1); } MyTransparentGeometry.EndParticleProfilingBlock(); //This gets 0.44ms for 2000 particles MyTransparentGeometry.StartParticleProfilingBlock("billboard.Start"); billboard.MaterialEnum = (MyTransparentMaterialEnum)material1; billboard.BlendMaterial = (MyTransparentMaterialEnum)material2; billboard.BlendTextureRatio = textureBlendRatio; billboard.EnableColorize = false; billboard.Color = color * alpha * m_generation.GetEffect().UserColorMultiplier; MyTransparentGeometry.EndParticleProfilingBlock(); return(true); }
protected override bool EqualsValues(object value1, object value2) { return(MyMwcUtils.IsZero((Vector4)value1 - (Vector4)value2)); }
public override Vector3 GetCenter() { //We agreed that everything in our solar area is in plane System.Diagnostics.Debug.Assert(MyMwcUtils.IsZero(OrbitProperties.AreaCenter.Y)); return(OrbitProperties.AreaCenter); }