示例#1
0
    // Update is called once per frame
    void Update()
    {
        switch (estado)
        {
        case EstadoDaqui.preparandoTiro:
            transform.rotation = Quaternion.Lerp(
                transform.rotation,
                Rotation2D.GetRotation(transform.position, doHeroi.position), 10 * Time.deltaTime);

            tempoDecorrido += Time.deltaTime;

            if (tempoDecorrido > intervaloDeTiro)
            {
                estado = EstadoDaqui.emTiro;

                GameObject G = InstanciaLigando.Instantiate(projetil, transform.position, 10);
                G.AddComponent <ProjetilQuicavel>().Iniciar(transform.right, particulaTelegrafista, velDoProjetil);

                InstanciaLigando.Instantiate(particulaTelegrafista, transform.position, 5);
                VerificadorDeDistancia();
            }
            else if (Vector2.Distance(transform.position, doHeroi.position) > distanciaDeAparecer ||
                     Vector2.Distance(transform.position, doHeroi.position) < proximoDeMais)
            {
                estado = EstadoDaqui.emEspera;
                ShowHideEnemy(false);
                VerificadorDeDistancia();
            }
            break;
        }
    }
        public void TestObject()
        {
            Quaternion2D q1 = new Quaternion2D(2, 4);
            Quaternion2D q2 = new Quaternion2D(3, 5);

            Assert.AreEqual(q1.GetHashCode(), (new Quaternion2D(2, 4)).GetHashCode());
            Assert.AreNotEqual(q1.GetHashCode(), q2.GetHashCode());

            object o = new object();

            Assert.AreNotEqual(q1, o);
            o = q1;
            Assert.AreEqual(q1, o);
            o = q2;
            Assert.AreNotEqual(q1, o);

            StringAssert.AreEqualIgnoringCase(q1.ToString(), "(2, 4)");
            StringAssert.AreNotEqualIgnoringCase(q1.ToString(), q2.ToString());

            Quaternion2D q = new Quaternion2D();

            q.angle = Mathf.PI * 0.3f;
            Rotation2D rot = new Rotation2D(Mathf.PI * 0.3f);

            Assert.AreEqual(q * Vector2.right, rot.x);
        }
        public void Scene_FluentBuildTransformations_ShouldAdded()
        {
            var rotationCenterX = 10.0;
            var rotationCenterY = 15.0;
            var rotationAngle   = Math.PI / 2;

            var shapes1 = CreateShapes();
            var shapes2 = CreateShapes();

            //Old syntax: method to method
            var translation1   = new Translation2D(rotationCenterX, rotationCenterY);
            var rotation       = new Rotation2D(rotationAngle);
            var translation2   = new Translation2D(-rotationCenterX, -rotationCenterY);
            var transformation = Transformation2D.Compose(translation1, rotation, translation2);

            for (int i = 0; i < shapes1.Count; i++)
            {
                shapes1[i].Apply(transformation);
                shapes1[i].DoTransform();
            }

            //New syntax: fluent builder
            shapes2.Translate(rotationCenterX, rotationCenterY).Rotate(rotationAngle).Translate(-rotationCenterX, -rotationCenterY).DoTransform();

            shapes1.Shapes.Should().BeEquivalentTo(shapes2.Shapes);
        }
            public void Execute(Entity entity, int index, [ReadOnly] ref AntSeed seed, [ReadOnly] ref MapSize mapSize)
            {
                for (int i = 0; i < seed.Count; i++)
                {
                    var minPos           = new float2(-5f, -5f) + mapSize.Value * 0.5f;
                    var maxPos           = new float2(5f, 5f) + mapSize.Value * 0.5f;
                    var holdingResources = new HoldingResources();
                    holdingResources.Value = false;

                    var translation = new Translation2D();
                    translation.Value = this.Random.NextFloat2(minPos, maxPos);

                    var rotation = new Rotation2D();
                    rotation.Value = this.Random.NextFloat() * PI * 2f;

                    var speed = new Velocity();
                    speed.Value = seed.InitialSpeed;

                    var stats = new AntStats();
                    stats.Steering          = seed.RandomSteering;
                    stats.Acceleration      = seed.Acceleration;
                    stats.WallSteerStrength = seed.WallSteerStrength;
                    stats.GoalSteerStrength = seed.GoalSteerStrength;
                    stats.Brightness        = this.Random.NextFloat(.75f, 1.25f);

                    var ant = this.Buffer.Instantiate(seed.AntPrefab);
                    this.Buffer.SetComponent(ant, holdingResources);
                    this.Buffer.SetComponent(ant, translation);
                    this.Buffer.SetComponent(ant, rotation);
                    this.Buffer.SetComponent(ant, speed);
                    this.Buffer.SetComponent(ant, stats);
                }

                this.Buffer.RemoveComponent <AntSeed>(entity);
            }
示例#5
0
    private Room CreateRoomFromStack(Property.RoomFilter filter, bool specified, IntVector3 position, IntVector3 entry)
    {
        if (specified)
        {
            Debug.LogFormat("create room at {0},{1},{2}", position.x, position.y, position.z);
            Room result = null;
            if (dicRoomList.TryGetValue(position, out result) && result != null)
            {
                return(null);
            }
        }

        if (roomQueue.Count == 0)
        {
            RefillRoomQueue(15);
        }

        Property.Room roomProp = null;
        bool          isRoomGood;
        int           count = roomQueue.Count;

        do
        {
            if (--count < 0)
            {
                break;
            }

            roomProp   = roomQueue.Dequeue();
            isRoomGood = filter == null || filter.Check(roomProp);
            isRoomGood = isRoomGood && (specified ? roomProp.CanPlaceAt(position) : FindPlace(roomProp, out position, out entry));
            if (!isRoomGood)
            {
                roomQueue.Enqueue(roomProp);
                roomProp = null;
            }
        } while(!isRoomGood);

        Room roomInst = null;

        if (roomProp != null)
        {
            roomInst = new Room(roomProp);
            //make sure room has a connector to entry
            Rotation2D roomRot = roomInst.FaceTo(entry - position);
            //TODO: after we have position & rotation, check if this room can be placed in scene
            roomInst.Init(position, roomRot, Vector3.zero, Quaternion.identity);
        }

        return(roomInst);
    }
示例#6
0
        public ActorInstance.Room CreateLinkedRoom(IntVector3 logicPos, Rotation2D rot, Vector3 worldPos, Quaternion worldRot)
        {
            //Assuming there's no room-conflict
            ActorInstance.Room linkRoom = GameLoader.Instance.GetRoomByLogicPosition(logicPos + LogicPosition);
            if (linkRoom == null)
            {
                Room roomProp = Resources.Load <Room>(LinkRoomPath);
                if (roomProp != null)
                {
                    ActorInstance.Room instRoom = new ActorInstance.Room(roomProp);
                    instRoom.Init(logicPos + rot * LogicPosition, rot, worldPos + Position, worldRot * Quaternion.Euler(EulerRotation));
                    linkRoom = instRoom;
                }
            }

            return(linkRoom);
        }
    void SpawnarMagia(Vector3 pos, Vector3 dir = default(Vector3))
    {
        if (dir == default(Vector3))
        {
            dir = DirecaoNoPlano.NoUpNormalizado(transform.position, HeroPosition);
        }

        GameObject G = InstanciaLigando.Instantiate(setaSombria, pos, 10);

        EventAgregator.Publish(new StandardSendGameEvent(EventKey.disparaSom, SoundEffectID.lancaProjetilInimigo));

        G.AddComponent <ProjetilInimigo>().IniciarProjetilInimigo(dir,
                                                                  particulaDoTeleport, velDaMagia, SoundEffectID.lancaProjetilInimigo);


        G.transform.rotation = Rotation2D.GetRotation(dir);
    }
示例#8
0
文件: Room.cs 项目: brooshe/Roguelike
        public Rotation2D FaceTo(IntVector3 entry /*relative position*/)
        {
            Rotation2D rot = TurnRot(entry, false);

            if (ConnectorList != null)
            {
                foreach (Connector conn in ConnectorList)
                {
                    ConnectorSocket socket = conn.socket as ConnectorSocket;
                    if (socket.socketType == ConnectorSocket.TYPE.TYPE_RELATIVE && conn.Enterable())
                    {
                        rot *= TurnRot(socket.ConnectPos, true);
                        return(rot);
                    }
                }
            }
            return(Rotation2D.Identity);
        }
示例#9
0
文件: Room.cs 项目: brooshe/Roguelike
        public void Init(IntVector3 logicPos, Rotation2D rot, Vector3 worldPos, Quaternion worldRot)
        {
            if (bInit)
            {
                LogicPosition = logicPos;
                LogicRotation = rot;
                SetTransform(worldPos, worldRot);
                return;
            }

            LogicPosition = logicPos;
            LogicRotation = rot;

            SetTransform(worldPos, Quaternion.identity);

            bInit = true;

            GameLoader.Instance.RegisterRoom(this);

            if (ConnectorList != null)
            {
                foreach (Connector connector in ConnectorList)
                {
                    GameLoader.Instance.ConnectToWorld(connector);
                }
            }

            if (RoomProp.GroupRooms != null)
            {
                foreach (var roomLink in RoomProp.GroupRooms)
                {
                    if (LinkRooms == null)
                    {
                        LinkRooms = new List <Room>();
                    }
                    Room room = roomLink.CreateLinkedRoom(LogicPosition, LogicRotation, worldPos, worldRot);
                    LinkRooms.Add(room);
                }
            }

            PostRoomCreated();
        }
        protected void _UpdateSceneRegion()
        {
            // partially based on c++ t2dSceneWindow::setCurrentCameraPosition...doesn't do zoom window or mounting

            // resize base on aspect ratio if specified
            _extent = ApplyResize(_extent);

            // set scene range.
            // if we implement zooming this will need to change, see t2dSceneWindow::calculateCameraView.
            Vector2 centerPos = CenterPosition;

            if (Rotation == 0.0f)
            {
                _sceneMin.X = centerPos.X - _extent.X / (2 * _zoom);
                _sceneMin.Y = centerPos.Y - _extent.Y / (2 * _zoom);
                _sceneMax.X = centerPos.X + _extent.X / (2 * _zoom);
                _sceneMax.Y = centerPos.Y + _extent.Y / (2 * _zoom);
                _camToWorld = Matrix.Identity * Matrix.CreateScale(1 / _zoom);
            }
            else
            {
                Rotation2D rot = new Rotation2D(MathHelper.ToRadians(Rotation));
                Vector2 x = rot.X;
                Vector2 y = rot.Y;
                float xext = 0.5f * _extent.X * Math.Abs(x.X) + 0.5f * _extent.Y * Math.Abs(y.X);
                float yext = 0.5f * _extent.X * Math.Abs(x.Y) + 0.5f * _extent.Y * Math.Abs(y.Y);
                _sceneMin = _sceneMax = centerPos;
                _sceneMin.X -= xext * (1 / _zoom);
                _sceneMax.X += xext * (1 / _zoom);
                _sceneMin.Y -= yext * (1 / _zoom);
                _sceneMax.Y += yext * (1 / _zoom);
                _camToWorld = Matrix.CreateRotationZ(MathHelper.ToRadians(Rotation)) * Matrix.CreateScale(1 / _zoom);
            }

            _camToWorld.Translation = new Vector3(centerPos, 20.0f);
        }
示例#11
0
        /// <summary>
        /// Fire a tank shell.
        /// </summary>
        void _Fire()
        {
            T2DSceneObject proj = (T2DSceneObject)_projectileTemplate.Clone();
            proj.Rotation = SceneObject.Rotation;

            // Allow the projectile to blow up.
            CombustibleComponent cc =
                proj.Components.FindComponent<CombustibleComponent>();
            if (cc != null)
            {
                cc.ParentObject = SceneObject;
                // Assign a sound index to this projectile.
                cc.ParentSoundIndex = _nextFreeProjectileSound;
            }

            // Remove the firing player from the projectile's collides with
            // list and add AI players
            proj.Collision.CollidesWith -= _projectileDoNotHitType;
            //proj.Collision.CollidesWith += GameData.Instance.AIPlayerObjectType;

            // Calculate a firing solution
            Vector2 firepos = new Vector2(0.0f, -32.5f);
            Rotation2D rot = new Rotation2D(MathHelper.ToRadians(SceneObject.Rotation));
            firepos = rot.Rotate(firepos);
            proj.Position = SceneObject.Position + firepos;

            Vector2 vel = new Vector2();
            vel.X = (float)System.Math.Sin((double)MathHelper.ToRadians(-proj.Rotation)) *
                -_projectileVelocity;
            vel.Y = (float)System.Math.Cos((double)MathHelper.ToRadians(proj.Rotation)) *
                -_projectileVelocity;

            proj.Physics.Velocity = vel;

            Owner.Manager.Register(proj);

            // Apply an impulse to the firing player
            Vector2 impulse = new Vector2();
            impulse.X = (float)System.Math.Sin((double)MathHelper.ToRadians(
                -SceneObject.Rotation + 180.0f)) * -_projectileKickback;
            impulse.Y = (float)System.Math.Cos((double)MathHelper.ToRadians(
                SceneObject.Rotation - 180.0f)) * -_projectileKickback;
            SceneObject.Physics.ApplyImpulse(impulse);

            // Apply game pad vibration to the firing player if appropriate
            T2DStaticSprite psprite = SceneObject as T2DStaticSprite;
            if (psprite != null)
            {
                GamepadVibrationComponent vib =
                    psprite.Components.FindComponent<GamepadVibrationComponent>();
                if (vib != null)
                {
                    vib.SetHighSpeedVibration(0.1f, 0.5f);
                }
            }

            // Play muzzle flash particles
            T2DParticleEffect flash =
                SceneObject.GetMountedObject("muzzle") as T2DParticleEffect;
            if (flash != null)
            {
                flash.PlayEffect(false);
            }

            // Play sounds.  Projectile whistle sounds are buffered on us to
            // allow them to fade when the projectile is destroyed.  Otherwise
            // the sound would just stop.
            MindcraftersComponentsLibrary.SoundBank.PlayCue("fireShell");
            if (_projectileSounds[_nextFreeProjectileSound] != null &&
                _projectileSounds[_nextFreeProjectileSound].IsPlaying)
                _projectileSounds[_nextFreeProjectileSound].Stop(
                    AudioStopOptions.Immediate);
            _projectileSounds[_nextFreeProjectileSound] =
                MindcraftersComponentsLibrary.SoundBank.GetCue("shellWhistle");
            _projectileSounds[_nextFreeProjectileSound].Play();

            _nextFreeProjectileSound++;
            if (_nextFreeProjectileSound >= _maxProjectileSounds)
                _nextFreeProjectileSound = 0;

            //TODO: update shots fired statistic

            _countdownToFire = FireRate;
        }
示例#12
0
        void DoSpawn(SpriteSpawnerTest.SpawnData spawner, Material mat)
        {
            ComponentType[] type = new ComponentType[]
            {
                typeof(Position2D),
                typeof(Rotation2D),
                typeof(Scale),
                typeof(SpriteSheetAnimation),
                typeof(SpriteSheetMaterial),
                typeof(SpriteSheetColor),
                typeof(UVCell)
            };

            var em        = EntityManager;
            var archetype = em.CreateArchetype(type);

            NativeArray <Entity> entities = new NativeArray <Entity>(spawner.spriteCount, Allocator.Temp);

            em.CreateEntity(archetype, entities);

            int cellCount = CachedUVData.GetCellCount(mat);

            Random rand = new Random((uint)UnityEngine.Random.Range(0, int.MaxValue));
            Rect   area = spawner.GetSpawnArea();
            SpriteSheetMaterial material = new SpriteSheetMaterial {
                material = mat
            };
            var maxFrames = CachedUVData.GetCellCount(mat);

            //Debug.Log("Spawning entities and setting components");
            for (int i = 0; i < entities.Length; i++)
            {
                Entity e = entities[i];


                Scale scale = new Scale {
                    Value = rand.NextFloat(spawner.minScale, spawner.maxScale)
                };
                float2 p = rand.NextFloat2(area.min, area.max);


                Position2D pos = spawner.origin.xy + p;
                Rotation2D rot = new Rotation2D {
                    angle = spawner.rotation
                };

                int numFrames             = rand.NextInt(3, maxFrames / 2);
                int minFrame              = rand.NextInt(0, maxFrames - numFrames);
                SpriteSheetAnimation anim = new SpriteSheetAnimation
                {
                    play       = true,
                    repetition = SpriteSheetAnimation.RepetitionType.Loop,
                    fps        = rand.NextFloat(spawner.minFPS_, spawner.maxFPS_),
                    frameMin   = minFrame,
                    frameMax   = minFrame + numFrames
                };
                SpriteSheetColor color = UnityEngine.Random.ColorHSV(.35f, .75f);
                UVCell           cell  = new UVCell {
                    value = rand.NextInt(0, maxFrames)
                };

                em.SetComponentData(e, scale);
                em.SetComponentData(e, pos);
                em.SetComponentData(e, anim);
                em.SetComponentData(e, color);
                em.SetComponentData(e, cell);
                em.SetComponentData(e, rot);
                em.SetSharedComponentData(e, material);
            }
        }
        /* adds a single new item on the map. if  */
        private FlashGlanceRoundItemVO AddItem()
        {
            if (_allItems.Count >= MaxItems)
            {
                return(null);                             //map is full
            }
            SafeHashCodePoint      emptyPosition = GetEmptyPosition();
            FlashGlanceRoundItemVO item          = null;

            if (emptyPosition != null)
            {
                _freePositions.Remove(emptyPosition);
                int   rotation = (_random.NextDouble() <= _castedConfig.GetRotationProbabilityByLevel(CurrentDifficulty)) ? Rotation2D.GetRandom(false) : Rotation2D.DEGREE_0;
                float scale    = (float)((_random.NextDouble() <= _castedConfig.GetScalingProbabilityByLevel(CurrentDifficulty)) ? _random.NextDouble() * 0.3f + 0.7f : 1f);
                item = new FlashGlanceRoundItemVO(_lastItemId, _lastCypher, emptyPosition, rotation, scale, _colors[_colorIndex]);
                _allItems.Add(item);
                _solutionChain.Add(item);
                item.IsBusy = true;

                _lastItemId++;

                //generate next cypher
                string     formula = _castedConfig.GetNextItemFormulaByLevel(CurrentDifficulty);
                Expression exp     = _expressionParser.EvaluateExpression(formula);
                if (exp.Parameters.ContainsKey("x"))
                {
                    exp.Parameters["x"].Value = _lastCypher; // set the named parameter "x"
                }
                else
                {
                    exp.Parameters.Add("x", new Parameter("x")
                    {
                        Value = _lastCypher
                    });
                }
                int formulaResult = (int)exp.Value;
                _lastCypher = (formulaResult > 0) ? formulaResult : _lastCypher + 1;
            }

            //_logger.LogMessage(LogLevel.Informational, "New item created: " + item.ToString());

            return(item);
        }
        static bool _CheckIntervalIntersection(Vector2[] srcVertexList, Vector2[] dstVertexList, ref Vector2 vertexAxis, ref Vector2 refLocalOffset, ref Vector2 refLocalVelocity, ref Rotation2D refLocalRot, ref float timeAxis, float collisionTime)
        {
            // calculate intervals for source/destination
            Vector2 vertexAxisRotated = refLocalRot.Unrotate(vertexAxis);

            // Get the interval of the polygons projected onto the axis.  Min returned in x, max in y.
            Vector2 srcProj = _CalculateInterval(srcVertexList, ref vertexAxisRotated);
            Vector2 dstProj = _CalculateInterval(dstVertexList, ref vertexAxis);

            // add reference offset
            float srcOffset = Vector2.Dot(refLocalOffset, vertexAxis);

            srcProj += new Vector2(srcOffset, srcOffset);

            // calculate intervals

            // Calculate delta of min of one interval with max of the other.
            // Note that if the intervals overlap then both deltas must be negative.
            // I.e., delta>0 --> intervals don't overlap because one min greater than
            // the other max.
            float delta0 = srcProj.X - dstProj.Y;
            float delta1 = dstProj.X - srcProj.Y;

            // Are we seperated?
            if (delta0 > 0.0f || delta1 > 0.0f)
            {
                // Yes, so test the dynamic intervals

                // calculate speed along a particular axis
                float speed = Vector2.Dot(refLocalVelocity, vertexAxis);

                float epsilon = 0.0001f;
                // ignore small speeds
                if (Math.Abs(speed) < epsilon)
                    return false;

                // The smallest absolute value must be the separation.  The reason is that one
                // delta measures separation between intervals, the other measures the span of
                // the two intervals (we want separation, which is always smaller).  Convert separation
                // into time by dividing by the speed (adjust sign depending on whether we are going
                // from source to dest or not).
                timeAxis = delta0 * delta0 < delta1 * delta1 ? -delta0 / speed : delta1 / speed;

                // successful collision?
                return timeAxis >= 0.0f && timeAxis <= collisionTime;
            }
            else
            {
                // No, so we're overlapped.
                //
                // Let's get the interval of the smallest |delta0| and |delta1| and
                // encode it as a negative value to signify an overlap rather than
                // a disjoint collision in forward-time.

                timeAxis = (delta0 > delta1) ? delta0 : delta1;

                // Successful Collision!
                return true;
            }
        }
        /// <summary>
        /// Render all the particles in the emitter.  This method is called by particle effects
        /// and should not normally be called otherwise.
        /// </summary>
        /// <param name="vertexScratch">Scratch space for vertices.  Must contain enough space for all particles to be rendered.</param>
        /// <param name="vertexOffset">Offset into vertex scratch space for first vertex.  Will be udpated for later particles.</param>
        /// <param name="textureCoords">Array of texture coords.</param>
        /// <param name="normal">Precomputed normal for particle.</param>
        /// <param name="tangent">Precomputed tangent for particle.</param>
        public void RenderEmitter(GFXVertexFormat.PCTTBN[] vertexScratch,
            ref int vertexOffset,
            Vector2[] textureCoords,
            ref Vector4 normal,
            ref Vector4 tangent)
        {
            // Any emitter-data or Allocated Particles?
            if (CurrentEmitterData == null || Allocated == 0)
                return;

            // Sanity!
            Assert.Fatal(Head != T2DParticleManager.NodeEndMarker, "Particles allocated but none in emitter chain!");

            // Fetch Particle Manager Pool.
            T2DParticle[] particleManagerPool = T2DParticleManager.Instance.Pool;

            // Fetch Particle Count.
            int particleCount = Allocated;

            // Note Vertex base.
            int vertexBase = vertexOffset;

            // Fetch current index.
            int currentIndex = CurrentEmitterData.FirstInFrontOrder ? Tail : Head;

            // no need to dereference these more than once
            Vector2 pivot = _emitterData.ParticlePivotPoint;
            T2DKeyGraph redLife = _emitterData.RedChannelLife;
            T2DKeyGraph greenLife = _emitterData.GreenChannelLife;
            T2DKeyGraph blueLife = _emitterData.BlueChannelLife;
            T2DKeyGraph visibilityLife = _emitterData.VisibilityLife;
            T2DKeyGraph visibilityScale = _parentEffect.CurrentEffectData.VisibilityScale;

            // Iterate all allocated particles.
            while (currentIndex != -1)
            {
                // Calculate Particle unit-age, so that we can get size
                float unitAge = particleManagerPool[currentIndex].Age / particleManagerPool[currentIndex].Lifetime;

                // Scale Size
                //Vector2 renderSize = 0.5f * particleManagerPool[currentIndex]._size;
                Vector2 renderSize;
                Vector2.Multiply(ref particleManagerPool[currentIndex]._size, 0.5f, out renderSize);

                renderSize.X *= _emitterData.SizeXLife[unitAge];
                if (renderSize.X < 0.0f)
                    renderSize.X = 0.0f;
                if (_emitterData.FixedParticleAspect)
                    renderSize.Y = renderSize.X;
                else
                {
                    renderSize.Y *= _emitterData.SizeYLife[unitAge];
                    if (renderSize.Y < 0.0f)
                        renderSize.Y = 0.0f;
                }

                // Transform Particle, inline the math.
                Rotation2D rotation = new Rotation2D(MathHelper.ToRadians(particleManagerPool[currentIndex]._rotationAngle));

                //Vector2 center = particleManagerPool[currentIndex]._position + renderSize * pivot - rotation.Rotate(renderSize * pivot);
                Vector2 center;
                Vector2.Multiply(ref renderSize, ref pivot, out center);
                Vector2 rotate = rotation.Rotate(center);
                Vector2.Subtract(ref center, ref rotate, out center);
                Vector2.Add(ref particleManagerPool[currentIndex]._position, ref center, out center);

                //Vector2 x = renderSize.X * rotation.X;
                //Vector2 y = renderSize.Y * rotation.Y;
                Vector2 x, y;
                Vector2 rotX = rotation.X, rotY = rotation.Y;
                float renX = renderSize.X, renY = renderSize.Y;
                Vector2.Multiply(ref rotX, renX, out x);
                Vector2.Multiply(ref rotY, renY, out y);

                // Get the color for this particle
                float redValue = redLife[unitAge];
                float greenValue = greenLife[unitAge];
                float blueValue = blueLife[unitAge];
                float visibilityValue = visibilityLife[unitAge] * visibilityScale[unitAge];
                Color color = new Color((byte)(redValue * 255.0f), (byte)(greenValue * 255.0f), (byte)(blueValue * 255.0f), (byte)(visibilityValue * 255.0f));

                // Vertex #0.
                vertexScratch[vertexOffset++] = new GFXVertexFormat.PCTTBN(new Vector3(-x.X - y.X + center.X, -x.Y - y.Y + center.Y, 0.0f),
                                                                            color,
                                                                            textureCoords[0],
                                                                            new Vector2(0.0f, 0.0f),
                                                                            tangent, normal);

                // Vertex #1.
                vertexScratch[vertexOffset++] = new GFXVertexFormat.PCTTBN(new Vector3(x.X - y.X + center.X, x.Y - y.Y + center.Y, 0.0f),
                                                                            color,
                                                                            textureCoords[1],
                                                                            new Vector2(0.0f, 0.0f),
                                                                            tangent, normal);

                // Vertex #2.
                vertexScratch[vertexOffset++] = new GFXVertexFormat.PCTTBN(new Vector3(x.X + y.X + center.X, x.Y + y.Y + center.Y, 0.0f),
                                                                            color,
                                                                            textureCoords[2],
                                                                            new Vector2(0.0f, 0.0f),
                                                                            tangent, normal);

                // Vertex #3.
                vertexScratch[vertexOffset++] = new GFXVertexFormat.PCTTBN(new Vector3(y.X - x.X + center.X, y.Y - x.Y + center.Y, 0.0f),
                                                                            color,
                                                                            textureCoords[3],
                                                                            new Vector2(0.0f, 0.0f),
                                                                            tangent, normal);

                // Set to next index.
                currentIndex = CurrentEmitterData.FirstInFrontOrder ? particleManagerPool[currentIndex].Previous : particleManagerPool[currentIndex].Next;
            }
        }
        static bool _FindContactPoints(
            Vector2[] srcPoly, Vector2 srcPosition, Vector2 srcVelocity, ref Rotation2D srcRotation,
            Vector2[] dstPoly, Vector2 dstPosition, Vector2 dstVelocity, ref Rotation2D dstRotation,
            Vector2 collisionNormal, float collisionTime, Vector2[] srcContacts, Vector2[] dstContacts, out int contactCount)
        {
            // Reset Contact Count.
            contactCount = 0;

            // Find Source Support Points.
            int srcSupportCount = _FindSupportPoints(srcPoly, srcPosition, srcVelocity, ref srcRotation, collisionNormal, collisionTime, _srcSupportPoints);

            // No contacts without support-points!
            if (srcSupportCount == 0)
                return false;

            // Find Destination Support Points.
            int dstSupportCount = _FindSupportPoints(dstPoly, dstPosition, dstVelocity, ref dstRotation, -collisionNormal, collisionTime, _dstSupportPoints);

            // No contacts without support-points!
            if (dstSupportCount == 0)
                return false;

            // Trivial Contact Check.
            if (srcSupportCount == 1 && dstSupportCount == 1)
            {
                // Simple Contact.
                srcContacts[contactCount] = _srcSupportPoints[0];
                dstContacts[contactCount] = _dstSupportPoints[0];
                // Increase Contact Count.
                contactCount++;
                // Return Conversion.
                return true;
            }

            // Calculate Perpendicular Normal.
            Vector2 perpNormal = new Vector2(-collisionNormal.Y, collisionNormal.X);

            // Calculate Source/Destination Points.
            float srcMin = Vector2.Dot(_srcSupportPoints[0], perpNormal);
            float srcMax = srcMin;
            float dstMin = Vector2.Dot(_dstSupportPoints[0], perpNormal);
            float dstMax = dstMin;

            // Check for Two support-points for source.
            if (srcSupportCount == 2)
            {
                // Set Max.
                srcMax = Vector2.Dot(_srcSupportPoints[1], perpNormal);

                // Reoder (if needed).
                if (srcMax < srcMin)
                {
                    // Swap.
                    TorqueUtil.Swap(ref srcMin, ref srcMax);
                    // Swap Support Points.
                    TorqueUtil.Swap(ref _srcSupportPoints[0], ref _srcSupportPoints[1]);
                }
            }

            // Check for Two support-points for destination.
            if (dstSupportCount == 2)
            {
                // Set Max.
                dstMax = Vector2.Dot(_dstSupportPoints[1], perpNormal);

                // Reoder (if needed).
                if (dstMax < dstMin)
                {
                    // Swap.
                    TorqueUtil.Swap(ref dstMin, ref dstMax);
                    // Swap Support Points.
                    TorqueUtil.Swap(ref _dstSupportPoints[0], ref _dstSupportPoints[1]);
                }
            }

            // Contacts?
            if (srcMin > dstMax || dstMin > srcMax)
            {
                // if collision time is negative then we are fully overlapped, in which
                // case we don't do this test (this test is whether or not two oncoming edges
                // will pass through each other).
                if (collisionTime >= 0.0f)
                {
                    // Nope!
                    return false;
                }
            }

            // Projected Segment.
            Vector2 projSeg;

            if (srcMin > dstMin)
            {
                // Project Src->Dst.
                _ProjectPointToSegment(_srcSupportPoints[0], _dstSupportPoints[0], _dstSupportPoints[1], out projSeg);

                // Note Contacts.
                srcContacts[contactCount] = _srcSupportPoints[0];
                dstContacts[contactCount] = projSeg;

                // Increase Contact Count.
                contactCount++;
            }
            else
            {
                // Project Dst->Src.
                _ProjectPointToSegment(_dstSupportPoints[0], _srcSupportPoints[0], _srcSupportPoints[1], out projSeg);

                // Note Contacts.
                srcContacts[contactCount] = projSeg;
                dstContacts[contactCount] = _dstSupportPoints[0];

                // Increase Contact Count.
                contactCount++;
            }

            // Other Variants.
            if (srcMin != srcMax && dstMin != dstMax)
            {
                if (srcMax < dstMax)
                {
                    // Project.
                    _ProjectPointToSegment(_srcSupportPoints[1], _dstSupportPoints[0], _dstSupportPoints[1], out projSeg);

                    // Note Contacts.
                    srcContacts[contactCount] = _srcSupportPoints[1];
                    dstContacts[contactCount] = projSeg;

                    // Increase Contact Count.
                    contactCount++;
                }
                else
                {
                    // Project.
                    _ProjectPointToSegment(_dstSupportPoints[1], _srcSupportPoints[0], _srcSupportPoints[1], out projSeg);

                    // Note Contacts.
                    srcContacts[contactCount] = projSeg;
                    dstContacts[contactCount] = _dstSupportPoints[1];

                    // Increase Contact Count.
                    contactCount++;
                }
            }

            // Return Contacts.
            return true;
        }
        private Rectangle _GetNearbyTiles(float x, float y, float width, float height, float pad)
        {
            // use offset from tile map center.
            x -= _position.X;
            y -= _position.Y;

            if (Rotation != 0.0f)
            {
                // need to transform world-space box to tile map aligned box which includes
                // original box.
                Rotation2D rotation = new Rotation2D(MathHelper.ToRadians(Rotation));

                // figure tile space position
                Vector2 newPos = new Vector2(x, y);
                newPos = rotation.Unrotate(newPos);
                x = newPos.X;
                y = newPos.Y;

                // compute tile space width/height, expanded to include all
                // of original box in tile aligned box
                Vector2 xvec = rotation.X;
                Vector2 yvec = rotation.Y;
                float newWidth = width * Math.Abs(xvec.X) + height * Math.Abs(xvec.Y);
                float newHeight = width * Math.Abs(yvec.X) + height * Math.Abs(yvec.Y);
                width = newWidth;
                height = newHeight;
            }

            float minX, minY, maxX, maxY;

            minX = ((x - (width * 0.5f)) / _tileSize.X) + (_mapSize.X * 0.5f);
            maxX = ((x + (width * 0.5f)) / _tileSize.X) + (_mapSize.X * 0.5f);
            minY = ((y - (height * 0.5f)) / _tileSize.Y) + (_mapSize.Y * 0.5f);
            maxY = ((y + (height * 0.5f)) / _tileSize.Y) + (_mapSize.Y * 0.5f);

            minX -= pad;
            minY -= pad;
            maxX += pad;
            maxY += pad;

            // make sure that returned rectangle only contains valid tile boundaries
            minX = MathHelper.Clamp(minX, 0.0f, _mapSize.X - 1);
            maxX = MathHelper.Clamp(maxX + 1, 0.0f, _mapSize.X - 1);
            minY = MathHelper.Clamp(minY, 0.0f, _mapSize.Y - 1);
            maxY = MathHelper.Clamp(maxY + 1, 0.0f, _mapSize.Y - 1);

            return new Rectangle((int)minX, (int)minY, (int)(maxX), (int)(maxY));
        }
        public override void Render(SceneRenderState srs)
        {
            Assert.Fatal(_renderedTileTypes.Count == 0, "previous render tiles not cleared");

            #if DEBUG
            Profiler.Instance.StartBlock("T2DTileLayer.Render");
            #endif

            if (_vb.IsNull)
                _CreateAndFillVB();

            T2DSceneCamera cam = _sceneGraph.Camera as T2DSceneCamera;
            Vector2 camExtent = (cam.SceneMax - cam.SceneMin); // we want world space extents
            Vector2 camCenter = cam.CenterPosition;
            Rectangle r = _GetNearbyTiles(camCenter.X, camCenter.Y, camExtent.X, camExtent.Y, 0.1f);

            // Get rotation and tile radius for q&d check to see if tile
            // is on screen (for rotated case).
            float tileRadius = 0.51f * _tileSize.Length();
            Rotation2D mapRotation = new Rotation2D(MathHelper.ToRadians(Rotation));

            Matrix mapToWorld = Matrix.CreateRotationZ(MathHelper.ToRadians(Rotation)) * Matrix.CreateTranslation(Position.X, Position.Y, 0.0f);

            // track how many tiles we'll actually render
            int tileCount = 0;

            // collect all the tiles we're actually going to render and put them in the right batch
            bool doCheckRotation = _rotation != 0.0f;
            for (int j = r.Top; j <= r.Height; j++)
            {
                for (int i = r.Left; i <= r.Width; i++)
                {
                    T2DTileObject tile = GetTileByGridCoords(i, j);
                    if (tile == null)
                        continue;

                    // check for off-screen tiles (rotated case, but doesn't cull tiles off screen due to camera rotation)
                    if (doCheckRotation)
                    {
                        Vector2 tilePos = tile.GetTileLocalPosition(_mapSize, _tileSize);
                        Vector2 tileWorldPos = mapRotation.Rotate(tilePos) + Position;
                        if (Math.Abs(tileWorldPos.X - camCenter.X) - tileRadius > 0.5f * camExtent.X || Math.Abs(tileWorldPos.Y - camCenter.Y) - tileRadius > 0.5f * camExtent.Y)
                            continue;
                    }

                    // at this point we're committed to rendering this tile
                    // for now simply add to the list of tiles for that
                    // tile type so we can batch them up later
                    tileCount++;
                    int tileIdx = i + j * (int)_mapSize.X;
                    if (tile.TileType._renderTiles.Count == 0)
                        _renderedTileTypes.Add(tile.TileType);
                    tile.TileType._renderTiles.Add(tileIdx);
                }
            }

            // Assuming we found some tiles, render all the batches.
            // Note: can't set 0 length index buffer without crashing, so
            // need to skip out of that case.
            if (tileCount != 0)
            {
                // We now know how many tiles we're going to render.  Is our index buffer big enough?
                if (_indexBuffer.IsNull)
                {
                    // index buffer cleared out...start over with size
                    _renderIndexCount = 0;
                }

                if (tileCount * 6 > _renderIndexCount)
                {
                    if (!_indexBuffer.IsNull)
                    {
                        _indexBuffer.Instance.Dispose();
                        _indexBuffer.Invalidate();
                    }
                    _renderIndexCount = tileCount * 8; // go a little higher than current max
                    _indexBuffer = ResourceManager.Instance.CreateDynamicIndexBuffer(ResourceProfiles.ManualDynamicIBProfile, _renderIndexCount * sizeof(UInt16), IndexElementSize.SixteenBits);
                }
                UInt16[] indexScratch = TorqueUtil.GetScratchArray<UInt16>(tileCount * 6);

                // render tile types in batches
                int idx = 0;
                srs.World.Push();
                srs.World.MultiplyMatrixLocal(mapToWorld);
                Matrix worldTransform = srs.World.Top;
                VertexDeclaration vd = GFXVertexFormat.GetVertexDeclaration(srs.Gfx.Device);
                for (int i = 0; i < _renderedTileTypes.Count; i++)
                {
                    T2DTileType tileType = _renderedTileTypes[i];

                    RenderInstance ri = SceneRenderer.RenderManager.AllocateInstance();

                    ri.Type = RenderInstance.RenderInstanceType.Mesh2D;

                    ri.ObjectTransform = worldTransform;

                    ri.PrimitiveType = PrimitiveType.TriangleList;
                    ri.VertexDeclaration = vd;

                    ri.VertexBuffer = _vb.Instance;
                    ri.VertexSize = GFXVertexFormat.VertexSize;
                    ri.BaseVertex = 0;
                    ri.VertexCount = 4 * (int)_mapSize.X * (int)_mapSize.Y;
                    ri.IndexBuffer = _indexBuffer.Instance;
                    ri.StartIndex = idx;
                    ri.PrimitiveCount = tileType._renderTiles.Count * 2;

                    ri.Opacity = VisibilityLevel;
                    ri.UTextureAddressMode = TextureAddressMode.Clamp;
                    ri.VTextureAddressMode = TextureAddressMode.Clamp;

                    ri.Material = tileType.Material;

                    // fill up index buffer
                    for (int j = 0; j < tileType._renderTiles.Count; j++)
                    {
                        int tileIdx = tileType._renderTiles[j];
                        Assert.Fatal(tileIdx * 4 + 3 < UInt16.MaxValue,
                           "T2DTileLayer.Render - Got out of range tile index!");
                        indexScratch[idx++] = (UInt16)(4 * tileIdx + 0);
                        indexScratch[idx++] = (UInt16)(4 * tileIdx + 1);
                        indexScratch[idx++] = (UInt16)(4 * tileIdx + 2);
                        indexScratch[idx++] = (UInt16)(4 * tileIdx + 0);
                        indexScratch[idx++] = (UInt16)(4 * tileIdx + 2);
                        indexScratch[idx++] = (UInt16)(4 * tileIdx + 3);
                    }
                    tileType._renderTiles.Clear();

                    SceneRenderer.RenderManager.AddInstance(ri);
                }
                srs.World.Pop();

                // rendered all the batches
                _renderedTileTypes.Clear();

                // set index data
                GFXDevice.Instance.Device.Indices = null;
            #if XBOX
                _indexBuffer.Instance.SetData<UInt16>(indexScratch, 0, idx); // XBox cannot discard... performance issue?
            #else
                _indexBuffer.Instance.SetData<UInt16>(indexScratch, 0, idx, SetDataOptions.Discard);
            #endif
            }

            // Renders custom collision polys for tiles based on tile types
            if (RenderCollisionBounds)
            {
                Matrix scaleMat = Matrix.CreateScale(_tileSize.X * 0.5f, _tileSize.Y * 0.5f, 1.0f);
                for (int j = r.Top; j <= r.Height; j++)
                {
                    for (int i = r.Left; i <= r.Width; i++)
                    {
                        T2DTileObject tile = GetTileByGridCoords(i, j);
                        if (tile == null || tile.TileType.CollisionPolyBasis == null)
                            continue;

                        // this is debug code so don't worry about all the math
                        Vector2 tilePos = tile.GetTileLocalPosition(_mapSize, _tileSize);
                        Matrix transMat = Matrix.CreateTranslation(tilePos.X, tilePos.Y, 0.0f);
                        Matrix tileToWorld = scaleMat * transMat * mapToWorld;

                        _RenderTileBounds(srs, ref tileToWorld, tile);
                    }
                }
            }

            #if DEBUG
            Profiler.Instance.EndBlock("T2DTileLayer.Render");
            #endif
        }
 /// <summary>
 /// Find world position of tile assuming it belongs to tile layer with the specified parameters.
 /// </summary>
 /// <param name="mapPos">Position of the tile layer in world coordinates.</param>
 /// <param name="mapRotation">Rotation of the tile layer in degrees.</param>
 /// <param name="mapSize">Dimensions of the tile layer.</param>
 /// <param name="tileSize">Size of each tile in the tile layer.</param>
 /// <returns>World position of tile.</returns>
 public Vector2 GetWorldPosition(Vector2 mapPos, float mapRotation, Vector2 mapSize, Vector2 tileSize)
 {
     Vector2 local = GetTileLocalPosition(mapSize, tileSize);
     if (mapRotation != 0.0f)
     {
         Rotation2D rotate = new Rotation2D(MathHelper.ToRadians(mapRotation));
         return rotate.Rotate(local) + mapPos;
     }
     else
         return local + mapPos;
 }
        public static bool IntersectMovingPolyPoly(
            float elapsedTime, Vector2[] srcVertexList, Vector2[] dstVertexList,
            Vector2 srcPosition, Vector2 dstPosition,
            float srcRotation, float dstRotation,
            Vector2 srcVelocity, Vector2 dstVelocity,
            ref Vector2 collisionPosition, ref Vector2 collisionNormal, ref Vector2 collisionPenetration, ref float time)
        {
            if (srcVertexList == null || dstVertexList == null)
                return false;

            int srcVertexCount = srcVertexList.Length;
            int dstVertexCount = dstVertexList.Length;

            //src
            Rotation2D srcRot = new Rotation2D(MathHelper.ToRadians(srcRotation));

            //dst
            Rotation2D dstInverseRot = new Rotation2D(MathHelper.ToRadians(-dstRotation));
            Rotation2D refLocalRot = srcRot * dstInverseRot;

            Vector2 offset = srcPosition - dstPosition;
            Vector2 refLocalOffset = dstInverseRot.Rotate(offset);

            Vector2 velocity = srcVelocity - dstVelocity;
            Vector2 refLocalVelocity = dstInverseRot.Rotate(velocity);

            float refVelSqr = Vector2.Dot(refLocalVelocity, refLocalVelocity);

            int axesCount = 0;

            float fullTimeStep = elapsedTime;

            float Epsilon = 0.0001f;

            // Ignore small velocities!
            if (refVelSqr > Epsilon)
            {
                // Set Axis.
                _vertexAxis[axesCount] = new Vector2(-refLocalVelocity.Y, refLocalVelocity.X);
                // Check Interval Intersection.
                if (!_CheckIntervalIntersection(
                        srcVertexList,
                        dstVertexList,
                        ref _vertexAxis[axesCount],
                        ref refLocalOffset, ref refLocalVelocity, ref refLocalRot,
                        ref _timeAxis[axesCount], fullTimeStep))
                    // No Collision!
                    return false;

                // Next Axes.
                axesCount++;
            }

            // Test Seperation Axes for Source Object.
            // NOTE:- We ignore if it's a point!
            if (srcVertexCount > 1)
            {
                for (int j = srcVertexCount - 1, i = 0; i < srcVertexCount; j = i, i++)
                {
                    // fetch the edge
                    Vector2 dP = srcVertexList[i] - srcVertexList[j];
                    Vector2 dP2 = new Vector2(-dP.Y, dP.X);
                    _vertexAxis[axesCount] = refLocalRot.Rotate(dP2);

                    // check interval intersection
                    if (!_CheckIntervalIntersection(srcVertexList, dstVertexList, ref _vertexAxis[axesCount], ref refLocalOffset, ref refLocalVelocity, ref refLocalRot, ref _timeAxis[axesCount], fullTimeStep))
                        return false;

                    //next axes
                    axesCount++;
                }
            }

            // Test Seperation Axes for Destination Object.
            // NOTE:- We ignore if it's a point!
            if (dstVertexCount > 1)
            {
                for (int j = dstVertexCount - 1, i = 0; i < dstVertexCount; j = i, i++)
                {
                    // fetch the edge
                    Vector2 dP = dstVertexList[i] - dstVertexList[j];

                    // set the axis
                    _vertexAxis[axesCount] = new Vector2(-dP.Y, dP.X);

                    if (!_CheckIntervalIntersection(srcVertexList, dstVertexList, ref _vertexAxis[axesCount], ref refLocalOffset, ref refLocalVelocity, ref refLocalRot, ref _timeAxis[axesCount], fullTimeStep))
                        return false;

                    //next axes
                    axesCount++;
                }
            }

            // Test Special-Case for Segments for Destination Object.
            if (dstVertexCount == 2)
            {
                // Set Axis.
                _vertexAxis[axesCount] = (dstVertexList[1] - dstVertexList[0]);

                // Check Interval Intersection.
                if (!_CheckIntervalIntersection(srcVertexList, dstVertexList, ref _vertexAxis[axesCount], ref refLocalOffset, ref refLocalVelocity, ref refLocalRot, ref _timeAxis[axesCount], fullTimeStep))
                    // No Collision!
                    return false;

                // Next Axes.
                axesCount++;
            }

            // Test Special-Case for Segments for Source Object.
            if (srcVertexCount == 2)
            {
                // Set Axis.

                Vector2 segment = (srcVertexList[1] - srcVertexList[0]);
                _vertexAxis[axesCount] = refLocalRot.Rotate(segment);

                // Check Interval Intersection.
                if (!_CheckIntervalIntersection(srcVertexList, dstVertexList, ref _vertexAxis[axesCount], ref refLocalOffset, ref refLocalVelocity, ref refLocalRot, ref _timeAxis[axesCount], fullTimeStep))
                    // No Collision!
                    return false;

                // Next Axes.
                axesCount++;
            }

            // find minimum seperation distance
            if (!_FindCollisionTime(_vertexAxis, _timeAxis, axesCount, ref collisionNormal, ref time))
                return false;

            // Respace Normal.
            collisionNormal = dstInverseRot.Unrotate(collisionNormal);

            // need this below (simple transpose)
            Rotation2D dstRot = dstInverseRot.Invert();

            // compute offset between poly centers for following calculation
            Vector2 polyCenter = new Vector2();
            foreach (Vector2 v in srcVertexList)
                polyCenter += v;
            polyCenter *= 1.0f / (float)srcVertexList.Length;
            Vector2 polyOffset = srcPosition + srcRot.Rotate(polyCenter);
            polyCenter = new Vector2();
            foreach (Vector2 v in dstVertexList)
                polyCenter += v;
            polyCenter *= 1.0f / (float)dstVertexList.Length;
            polyOffset -= dstPosition + dstRot.Rotate(polyCenter);

            // Make sure the collision polygons are pushed away.
            // NOTE: This is the overlap case.
            if (Vector2.Dot(collisionNormal, polyOffset) < 0.0f)
                collisionNormal = -collisionNormal;

            int contactCount = 0;
            if (!_FindContactPoints(
                    srcVertexList, srcPosition, srcVelocity, ref srcRot,
                    dstVertexList, dstPosition, dstVelocity, ref dstRot,
                    collisionNormal, time, _srcContacts, _dstContacts, out contactCount))
                // No Support Points!
                return false;

            collisionPosition = 0.5f * (_srcContacts[0] + _dstContacts[0]);
            collisionPenetration = _dstContacts[0] - _srcContacts[0];
            if (contactCount == 2)
            {
                collisionPosition = 0.5f * collisionPosition + 0.25f * (_srcContacts[1] + _dstContacts[1]);
                Vector2 collisionPenetration2 = _dstContacts[1] - _srcContacts[1];
                if (collisionPenetration2.LengthSquared() > collisionPenetration.LengthSquared())
                    collisionPenetration = collisionPenetration2;
            }

            // return true to indicate collision
            return true;
        }
        //-----------------------------------------------------------------------------------------------
        // Transform Contact-Point into World-Space Collision.
        //-----------------------------------------------------------------------------------------------
        static void _TransformContact(Vector2 vertex, Vector2 position, Vector2 velocity, ref Rotation2D rotation, float collisionTime, out Vector2 contact)
        {
            // Do Transformation.
            contact = position + rotation.Rotate(vertex);

            // Check Time.
            if (collisionTime > 0.0f)
                contact += velocity * collisionTime;
        }
        //-----------------------------------------------------------------------------------------------
        // Find Support Points.
        // NOTE:-   This is a convex shape along a specified direction.
        //-----------------------------------------------------------------------------------------------
        static int _FindSupportPoints(
            Vector2[] poly, Vector2 position, Vector2 velocity, ref Rotation2D rotation,
            Vector2 collisionNormal, float collisionTime, Vector2[] supportPoints)
        {
            // Calculate Normal.
            Vector2 normal = rotation.Unrotate(collisionNormal);

            // Reset Direction.
            float supportMin = _support[0] = Vector2.Dot(poly[0], normal);

            // Interate Polygon.
            for (int i = 1; i < poly.Length; i++)
            {
                // Calculate.
                _support[i] = Vector2.Dot(poly[i], normal);

                // Check For Minimum.
                if (_support[i] < supportMin)
                    supportMin = _support[i];
            }

            // The limit here is two support-points only.
            // If we find more then we use the extremums.
            int supportCount = 0;

            // Set Threshold.
            float threshold = 1.0e-3f;

            // Reset Sign Flag.
            bool sign = false;

            // Calculate Perpendicular Normal.
            Vector2 perpNormal = new Vector2(-collisionNormal.Y, collisionNormal.X);

            // Interate Polygon.
            for (int i = 0; i < poly.Length; i++)
            {
                // Check Contact.
                if (_support[i] < supportMin + threshold)
                {
                    // Transform Contact to World-Space.
                    Vector2 contact;
                    _TransformContact(poly[i], position, velocity, ref rotation, collisionTime, out contact);
                    // Contact Dot.
                    float contactDot = Vector2.Dot(contact, perpNormal);
                    // Less than two supports?
                    if (supportCount < 2)
                    {
                        // Yes, so note contact.
                        _supportMinMax[supportCount] = contactDot;
                        supportPoints[supportCount] = contact;
                        // Increase Support Count.
                        supportCount++;

                        // Note Sign for two contacts.
                        if (supportCount > 1)
                            sign = (_supportMinMax[1] > _supportMinMax[0]);
                    }
                    else
                    {
                        int idx0 = 0;
                        int idx1 = 1;
                        if (!sign)
                            TorqueUtil.Swap(ref idx0, ref idx1);
                        if (contactDot < _supportMinMax[idx0])
                        {
                            _supportMinMax[idx0] = contactDot;
                            supportPoints[idx0] = contact;

                        }
                        else if (contactDot > _supportMinMax[idx1])
                        {
                            _supportMinMax[idx1] = contactDot;
                            supportPoints[idx1] = contact;
                        }

                    }
                }
            }

            // Return Support Count.
            return supportCount;
        }