static DrawUtil()
        {
            _vertexSet4[0] = new GFXVertexFormat.PCTTBN();
            _vertexSet4[1] = new GFXVertexFormat.PCTTBN();
            _vertexSet4[2] = new GFXVertexFormat.PCTTBN();
            _vertexSet4[3] = new GFXVertexFormat.PCTTBN();

            _vertexSet10[0] = new GFXVertexFormat.PCTTBN();
            _vertexSet10[1] = new GFXVertexFormat.PCTTBN();
            _vertexSet10[2] = new GFXVertexFormat.PCTTBN();
            _vertexSet10[3] = new GFXVertexFormat.PCTTBN();
            _vertexSet10[4] = new GFXVertexFormat.PCTTBN();
            _vertexSet10[5] = new GFXVertexFormat.PCTTBN();
            _vertexSet10[6] = new GFXVertexFormat.PCTTBN();
            _vertexSet10[7] = new GFXVertexFormat.PCTTBN();
            _vertexSet10[8] = new GFXVertexFormat.PCTTBN();
            _vertexSet10[9] = new GFXVertexFormat.PCTTBN();
        }
        private void _FillVB()
        {
            Assert.Fatal(!_vb.IsNull, "doh");
            Assert.Fatal(_vertices.Length > 0, "doh");

            int numVerts = _vertices.Length + 1;

            // fill in vertex array
            int sizeInBytes = numVerts * GFXVertexFormat.VertexSize;
            GFXVertexFormat.PCTTBN[] vertices = TorqueUtil.GetScratchArray<GFXVertexFormat.PCTTBN>(numVerts);
            for (int i = 0; i < numVerts - 1; ++i)
            {
                vertices[i] = new GFXVertexFormat.PCTTBN();
                vertices[i].Position = new Vector3(_vertices[i].X, _vertices[i].Y, 0.0f);
                vertices[i].Color = new Color(_color);
            }
            vertices[numVerts - 1] = vertices[0];

            _vb.Instance.SetData<GFXVertexFormat.PCTTBN>(vertices, 0, numVerts);

            _refillVB = false;
        }
        /// <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;
            }
        }
        void _RenderTileBounds(SceneRenderState srs, ref Matrix objToWorld, T2DTileObject tile)
        {
            int numVerts = tile.TileType.CollisionPolyBasis.Length + 1;
            if (tile.TileType._collisionPolyVB.IsNull)
            {
                int sizeInBytes = numVerts * GFXVertexFormat.VertexSize;
                tile.TileType._collisionPolyVB = ResourceManager.Instance.CreateDynamicVertexBuffer(ResourceProfiles.ManualStaticVBProfile, sizeInBytes);

                // fill in vertex array
                GFXVertexFormat.PCTTBN[] pVertices = TorqueUtil.GetScratchArray<GFXVertexFormat.PCTTBN>(numVerts);
                for (int k = 0; k < numVerts - 1; ++k)
                {
                    pVertices[k] = new GFXVertexFormat.PCTTBN();
                    pVertices[k].Position = new Vector3(tile.TileType.CollisionPolyBasis[k].X, tile.TileType.CollisionPolyBasis[k].Y, 0.0f);
                    pVertices[k].Color = Color.Green;
                }
                pVertices[numVerts - 1] = pVertices[0];

                tile.TileType._collisionPolyVB.Instance.SetData<GFXVertexFormat.PCTTBN>(pVertices, 0, numVerts);
            }

            srs.World.Push();
            srs.World.MultiplyMatrixLocal(objToWorld);
            float flipx = tile.FlipX ? -1.0f : 1.0f;
            float flipy = tile.FlipY ? -1.0f : 1.0f;
            srs.World.MultiplyMatrixLocal(Matrix.CreateScale(new Vector3(flipx, flipy, 1.0f)));

            if (_effect == null)
            {
                _effect = new GarageGames.Torque.Materials.SimpleMaterial();
            }

            RenderInstance ri = SceneRenderer.RenderManager.AllocateInstance();
            ri.Type = RenderInstance.RenderInstanceType.Mesh2D;
            ri.ObjectTransform = srs.World.Top;
            ri.VertexBuffer = tile.TileType._collisionPolyVB.Instance;
            ri.PrimitiveType = PrimitiveType.LineStrip;
            ri.VertexSize = GFXVertexFormat.VertexSize;
            ri.VertexDeclaration = GFXVertexFormat.GetVertexDeclaration(srs.Gfx.Device);
            ri.VertexCount = numVerts;
            ri.BaseVertex = 0;
            ri.PrimitiveCount = numVerts - 1;

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

            ri.Material = _effect;
            SceneRenderer.RenderManager.AddInstance(ri);

            srs.World.Pop();
        }
        void _CreateAndFillVB()
        {
            Assert.Fatal(_vb.IsNull, "About to leak a vertex buffer");

            // create the new buffer of the correct size
            int numVerts = 4 * (int)_mapSize.X * (int)_mapSize.Y;
            int sizeInBytes = numVerts * GFXVertexFormat.VertexSize;
            _vb = ResourceManager.Instance.CreateDynamicVertexBuffer(ResourceProfiles.ManualStaticVBProfile, sizeInBytes);

            // create some values which will be constant over entire vertex space
            Color color = Color.White;
            Vector4 normal, tangent, binormal;
            _CreateTangentSpace(out normal, out tangent, out binormal);

            Vector2 t0 = new Vector2(0, 0);
            Vector2 t1 = new Vector2(1, 0);
            Vector2 t2 = new Vector2(1, 1);
            Vector2 t3 = new Vector2(0, 1);

            // fill in vertex array
            GFXVertexFormat.PCTTBN[] vertices = TorqueUtil.GetScratchArray<GFXVertexFormat.PCTTBN>(numVerts);
            for (int x = 0; x < (int)_mapSize.X; x++)
            {
                for (int y = 0; y < (int)_mapSize.Y; y++)
                {
                    int tileIdx = x + y * (int)_mapSize.X;

                    T2DTileObject tile = GetTileByGridCoords(x, y);
                    if (tile != null)
                    {
                        // get the region coordinates for this tile
                        tile.TileType.Material.GetRegionCoords(tile.TileType.MaterialRegionIndex, out t0, out t1, out t2, out t3);

                        // flip the coordinstes if neccesary
                        if (tile.FlipX != FlipX)
                        {
                            TorqueUtil.Swap<Vector2>(ref t0, ref t1);
                            TorqueUtil.Swap<Vector2>(ref t2, ref t3);
                        }
                        if (tile.FlipY != FlipY)
                        {
                            TorqueUtil.Swap<Vector2>(ref t0, ref t3);
                            TorqueUtil.Swap<Vector2>(ref t1, ref t2);
                        }
                    }

                    // get tile extents
                    float minx = _tileSize.X * (float)x - 0.5f * _mapSize.X * _tileSize.X;
                    float maxx = _tileSize.X * (float)(x + 1) - 0.5f * _mapSize.X * _tileSize.X;
                    float miny = _tileSize.Y * (float)y - 0.5f * _mapSize.Y * _tileSize.Y;
                    float maxy = _tileSize.Y * (float)(y + 1) - 0.5f * _mapSize.Y * _tileSize.Y;

                    vertices[4 * tileIdx + 0] = new GFXVertexFormat.PCTTBN(
                        new Vector3(minx, miny, 0.0f),
                        color,
                        t0,
                        t0,
                        tangent,
                        normal);

                    vertices[4 * tileIdx + 1] = new GFXVertexFormat.PCTTBN(
                        new Vector3(maxx, miny, 0.0f),
                        color,
                        t1,
                        t1,
                        tangent,
                        normal);

                    vertices[4 * tileIdx + 2] = new GFXVertexFormat.PCTTBN(
                        new Vector3(maxx, maxy, 0.0f),
                        color,
                        t2,
                        t2,
                        tangent,
                        normal);

                    vertices[4 * tileIdx + 3] = new GFXVertexFormat.PCTTBN(
                        new Vector3(minx, maxy, 0.0f),
                        color,
                        t3,
                        t3,
                        tangent,
                        normal);
                }
            }

            _vb.Instance.SetData<GFXVertexFormat.PCTTBN>(vertices, 0, numVerts);
        }
        protected void _RenderPolygon(Matrix objToWorld, SceneRenderState srs, Vector2[] vertices, Color color)
        {
            GraphicsDevice d3d = srs.Gfx.Device;
            Assert.Fatal(d3d != null, "doh");

            Assert.Fatal(vertices.Length > 0, "no vertices to render!");

            int numVerts = vertices.Length + 1;

            // make sure we have a vertex buffer
            if (_vb.IsNull)
            {
                int sizeInBytes = numVerts * GFXVertexFormat.VertexSize;
                _vb = ResourceManager.Instance.CreateDynamicVertexBuffer(ResourceProfiles.ManualStaticVBProfile, sizeInBytes);
            }

            // deal with flip
            float flipx = SceneObject != null && SceneObject.FlipX ? -1.0f : 1.0f;
            float flipy = SceneObject != null && SceneObject.FlipY ? -1.0f : 1.0f;

            // fill in vertex array
            GFXVertexFormat.PCTTBN[] pVertices = TorqueUtil.GetScratchArray<GFXVertexFormat.PCTTBN>(numVerts);
            for (int i = 0; i < numVerts - 1; ++i)
            {
                pVertices[i] = new GFXVertexFormat.PCTTBN();
                pVertices[i].Position = new Vector3(flipx * vertices[i].X, flipy * vertices[i].Y, 0.0f);
                pVertices[i].Color = color;
            }
            pVertices[numVerts - 1] = pVertices[0];

            _vb.Instance.SetData<GFXVertexFormat.PCTTBN>(pVertices, 0, numVerts);

            srs.World.Push();
            srs.World.MultiplyMatrixLocal(objToWorld);

            if (_effect == null)
            {
                _effect = new GarageGames.Torque.Materials.SimpleMaterial();
            }

            RenderInstance ri = SceneRenderer.RenderManager.AllocateInstance();
            ri.Type = RenderInstance.RenderInstanceType.Mesh2D;
            ri.ObjectTransform = srs.World.Top;
            ri.VertexBuffer = _vb.Instance;
            ri.PrimitiveType = PrimitiveType.LineStrip;
            ri.VertexSize = GFXVertexFormat.VertexSize;
            ri.VertexDeclaration = GFXVertexFormat.GetVertexDeclaration(d3d);
            ri.VertexCount = numVerts;
            ri.BaseVertex = 0;
            ri.PrimitiveCount = numVerts - 1;

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

            ri.Material = _effect;
            SceneRenderer.RenderManager.AddInstance(ri);

            srs.World.Pop();
        }
        /// <summary>
        /// Copy the vertex data into an array.
        /// </summary>
        /// <param name="vb">The vertex array receiving the vertex data.</param>
        /// <param name="vbStart">The start index.</param>
        /// <param name="mat">The transform matrix to rotate vertex data with.</param>
        public void CopyVB(GFXVertexFormat.PCTTBN[] vb, int vbStart, Matrix mat)
        {
            _ComputeTangents();

            for (int i = 0, idx = vbStart; i < _verts.Length; ++i)
            {
                Vector3 tang = new Vector3(_tangents[i].X, _tangents[i].Y, _tangents[i].Z);
                Vector3 binormal = Vector3.Cross(_norms[i], tang) * _tangents[i].W;
                tang = Vector3.TransformNormal(tang, mat);
                binormal = Vector3.TransformNormal(binormal, mat);
                Vector3 vert = Vector3.Transform(_verts[i], mat);
                Vector3 norm = Vector3.TransformNormal(_norms[i], mat);

                vb[idx++] = new GFXVertexFormat.PCTTBN(
                    new Vector3(vert.X, vert.Y, vert.Z),
                    (_colors != null) ? _colors[i] : Color.White,
                    _tverts[i],
                    (_tverts2 != null) ? _tverts2[i] : _tverts[i],
                    new Vector4(tang.X, tang.Y, tang.Z, _tangents[i].W),
                    new Vector4(norm.X, norm.Y, norm.Z, 0.0f));
            }
        }
        public override void Render(int frame, int matFrame, Material[] materialList, SceneRenderState srs)
        {
            // update _verts and normals...
            UpdateSkin();

            if (_vb.IsNull)
                base.CreateVBIB();

            if (!_vb.IsNull)
            {
                int sizeInBytes = _initialVerts.Length * GFXVertexFormat.VertexSize;
                GFXVertexFormat.PCTTBN[] v = TorqueUtil.GetScratchArray<GFXVertexFormat.PCTTBN>(_initialVerts.Length);

                for (int i = 0; i < _initialVerts.Length; ++i)
                {
                    Vector3 tang = new Vector3(_tangents[i].X, _tangents[i].Y, _tangents[i].Z);
                    Vector3 binormal = Vector3.Cross(_norms[i], tang) * _tangents[i].W;
                    v[i] = new GFXVertexFormat.PCTTBN(
                        new Vector3(_verts[i].X, _verts[i].Y, _verts[i].Z),
                        Color.White,
                        _tverts[i],
                        _tverts[i],
                        _tangents[i],
                        new Vector4(_norms[i].X, _norms[i].Y, _norms[i].Z, 0.0f));
                }

                GFXDevice.Instance.Device.Textures[0] = null;

                _vb.Instance.SetData<GFXVertexFormat.PCTTBN>(v, 0, _initialVerts.Length, SetDataOptions.NoOverwrite);
            }

            base.Render(frame, matFrame, materialList, srs);

            RestoreSkin();
        }
        private void _FillVB()
        {
            Assert.Fatal(_vb != null, "doh");

            // Calculate our uv points.
            _uvs[0] = new Vector2(_uvMinX, _uvMinY);
            _uvs[1] = new Vector2(_uvMaxX, _uvMinY);
            _uvs[2] = new Vector2(_uvMaxX, _uvMaxY);
            _uvs[3] = new Vector2(_uvMinX, _uvMaxY);

            // Fill in vertex array.

            int sizeInBytes = _numVerts * GFXVertexFormat.VertexSize;
            GFXVertexFormat.PCTTBN[] vertices = _vb.GetScratchArray(_numVerts);

            for (int i = 0; i < _numVerts; ++i)
            {
                vertices[i] = new GFXVertexFormat.PCTTBN(
                    _points[i],
                    _color,
                    _uvs[i],
                    _uvs[i],
                    _tangent,
                    _normal);
            }

            // Pass array to the real buffer.
            _vb.SetData(vertices, 0, _numVerts);

            _refillVB = false;
        }