Example #1
0
            /// <summary>
            /// Adds a renderable mesh using this technique.
            /// </summary>
            /// <param name="addMesh">Add mesh</param>
            public void Add(RenderableMesh addMesh)
            {
                // Make sure this mesh uses the correct material
                if (addMesh.usedTechnique != technique)
                {
                    throw new ArgumentException("Invalid technique, to add a mesh to " +
                                                "MeshesPerMaterialPerTechniques it must use the specified " +
                                                "technique=" + technique.Name);
                }

                // Search for the used material, maybe we have it already in list.
                for (int listNum = 0; listNum < meshesPerMaterials.Count; listNum++)
                {
                    MeshesPerMaterial existingList = meshesPerMaterials[listNum];
                    if (existingList.material == addMesh.material)
                    {
                        // Just add
                        existingList.Add(addMesh);
                        return;
                    }
                }

                // Not found, create new list and add mesh there.
                MeshesPerMaterial newList = new MeshesPerMaterial(addMesh.material);

                newList.Add(addMesh);
                meshesPerMaterials.Add(newList);
            }
        public Cube()
        {
            _simpleMaterial = new SimpleMaterial();
            var resourceAllocator = new ResourceAllocator(new OpenGlResourceFactory());

            _simpleMaterial.Create();

            var mesh = MeshCreator.CreateXZGrid(10, 10);

            _renderable = resourceAllocator.AllocateResourceFor(mesh);
            _renderable.CreateVAO();
        }
Example #3
0
            /// <summary>
            /// Adds a renderable mesh using this material.
            /// </summary>
            /// <param name="addMesh">Add mesh</param>
            public void Add(RenderableMesh addMesh)
            {
                // Make sure this mesh uses the correct material
                if (addMesh.material != material)
                {
                    throw new ArgumentException("Invalid material, to add a mesh to " +
                                                "MeshesPerMaterial it must use the specified material=" +
                                                material);
                }

                meshes.Add(addMesh);
            }
        public void ComputeCoverage(RenderableMesh mesh, AABBf meshBounds, out long sideCoverage, out long topCoverage)
        {
            float longestSide = Math.Max(Math.Max(meshBounds.MaxX - meshBounds.MinX, meshBounds.MaxY - meshBounds.MinY), meshBounds.MaxZ - meshBounds.MinZ);
            float farPlane = longestSide * 2.0f;

            float x = (meshBounds.MinX + meshBounds.MaxX) / 2.0f;
            float y = meshBounds.MinY;
            float z = (meshBounds.MinZ + meshBounds.MaxZ) / 2.0f;
            Vector3 origin = new Vector3(x, y, z);
            Vector3 up = Vector3.UnitY;
            Vector3 look = -Vector3.UnitX;

            for (int i = 0; i < m_occlusionQueries.Length; i++)
            {
                Matrix4 orbit = Matrix4.CreateRotationY(MathHelper.DegreesToRadians((365 / 64.0f) * i));

                Matrix4 projection = Matrix4.CreatePerspectiveFieldOfView(MathHelper.DegreesToRadians(90), 1.0f, 0.1f, farPlane);
                Matrix4 view = Matrix4.LookAt(origin + Vector3.Transform(new Vector3(longestSide, 0, 0), orbit), origin, Vector3.TransformNormal(up, orbit));

                RenderView(view, projection, mesh, m_occlusionQueries[i]);

                //Bitmap bmp = GLEx.BitmapColorBuffer(m_pixelWidth, m_pixelHeight);
                //bmp.Save("C:\\test_" + i + ".bmp");
            }

            // Gather all the occlusion queries we performed
            long[] m_occlusionQueryResults = new long[64];
            for (int i = 0; i < m_occlusionQueries.Length; i++)
            {
                int ready = 0;
                while (ready == 0)
                {
                    GL.GetQueryObject(m_occlusionQueries[i], GetQueryObjectParam.QueryResultAvailable, out ready);
                }

                GL.GetQueryObject(m_occlusionQueries[i], GetQueryObjectParam.QueryResult, out m_occlusionQueryResults[i]);
            }

            // Reset the current frame buffer.
            GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, 0);

            long totalSidePixels = 0;
            long totalTopPixels = 0;
            for (int i = 0; i < m_occlusionQueries.Length; i++)
            {
                totalSidePixels += m_occlusionQueryResults[i];
            }

            sideCoverage = totalSidePixels;
            topCoverage = totalTopPixels;
        }
        }         // Add(vertexBuffer, indexBuffer, part)

        #endregion

        #region Render
        /// <summary>
        /// Render all meshes we collected this frame sorted by techniques
        /// and materials. This method is about 3-5 times faster than just
        /// using Model's Mesh.Draw method (see commented out code there).
        /// The reason for that is that we require only very few state changes
        /// and render everthing down as fast as we can. The only optimization
        /// left would be to put vertices of several meshes together if they
        /// are static and use the same technique and material. But since
        /// meshes have WriteOnly vertex and index buffers, we can't do that
        /// without using a custom model format.
        /// </summary>
        public void Render()
        {
            // Copy over last frame's object to this frame
            for (int listNum = 0; listNum < sortedMeshes.Count; listNum++)
            {
                MeshesPerMaterialPerTechniques list = sortedMeshes[listNum];
                for (int meshNum = 0; meshNum < list.meshesPerMaterials.Count; meshNum++)
                {
                    MeshesPerMaterial list2 = list.meshesPerMaterials[meshNum];
                    for (int num = 0; num < list2.meshes.Count; num++)
                    {
                        RenderableMesh mesh = list2.meshes[num];
                        // Copy over last frame matrices for rendering now!
                        mesh.lastFrameRenderMatricesAndAlpha =
                            mesh.thisFrameRenderMatricesAndAlpha;
                        // Clear list for this frame
                        mesh.thisFrameRenderMatricesAndAlpha =
                            new List <MatrixAndAlpha>();
                    }     // for
                }         // for
            }             // for

            // Make sure z buffer is on for 3D content
            BaseGame.Device.RenderState.DepthBufferEnable      = true;
            BaseGame.Device.RenderState.DepthBufferWriteEnable = true;

            // We always use the normalMapping shader here.
            Effect effect = BaseGame.ParallaxShader.Effect;

            // Set general parameters for the shader
            BaseGame.ParallaxShader.SetParametersOptimizedGeneral();

            // Don't set vertex buffer again if it does not change this frame.
            // Clear these remember settings.
            lastVertexBufferSet = null;
            lastIndexBufferSet  = null;

            //obs: foreach (MeshesPerMaterialPerTechniques list in sortedMeshes)
            for (int listNum = 0; listNum < sortedMeshes.Count; listNum++)
            {
                MeshesPerMaterialPerTechniques list = sortedMeshes[listNum];

                if (list.NumberOfRenderMatrices > 0)
                {
                    list.Render(effect);
                }
            }     // for (listNum)
        }         // Render()
        public void Dispose()
        {
            GC.SuppressFinalize(this);

            if (OriginalMesh != null)
            {
                OriginalMesh.Dispose();
                OriginalMesh = null;
            }

            if (OccluderMesh != null)
            {
                OccluderMesh.Dispose();
                OccluderMesh = null;
            }
        }
        void AddSphere()
        {
            scene.Root.AddChildren(node = new Node(new StringBuilder("Sphere")));

            sphereMesh = new RenderableMesh(editorEngine, GeometryFactory.CreateSphere(editorEngine, 3, 5));

            node.AddRenderable(sphereMesh);

            Material material = new Material("earth");

            MaterialLayer layer = material.CreateLayer();

            layer.DiffuseMap = editorEngine.Textures.CreateTexture2DFromFile(new StringBuilder("earth"));

            sphereMesh.Material = material;
        }
        }         // Render()

        #endregion

        #region ClearAll
        /// <summary>
        /// Clear all objects in the render list in case our device got lost.
        /// </summary>
        public void ClearAll()
        {
            // Copy over last frame's object to this frame
            for (int listNum = 0; listNum < sortedMeshes.Count; listNum++)
            {
                MeshesPerMaterialPerTechniques list = sortedMeshes[listNum];
                for (int meshNum = 0; meshNum < list.meshesPerMaterials.Count; meshNum++)
                {
                    MeshesPerMaterial list2 = list.meshesPerMaterials[meshNum];
                    for (int num = 0; num < list2.meshes.Count; num++)
                    {
                        RenderableMesh mesh = list2.meshes[num];
                        // Clear all
                        mesh.lastFrameRenderMatricesAndAlpha.Clear();
                        mesh.thisFrameRenderMatricesAndAlpha.Clear();
                    } // for
                }     // for
            }         // for
        }             // ClearAll()
            }             // Add(addMesh)

            #endregion

            #region Render
            /// <summary>
            /// Render all meshes that use this material.
            /// This method is only called if we got any meshes to render,
            /// which is determinated if NumberOfRenderMeshes is greater 0.
            /// </summary>
            public void Render()
            {
                // Set material settings. We don't have to update the shader here,
                // it will be done in RenderableMesh.Render anyway because of
                // updating the world matrix!
                BaseGame.ParallaxShader.SetParametersOptimized(material);
                // Set vertex declaration
                BaseGame.Device.VertexDeclaration = meshes[0].vertexDeclaration;

                // Render all meshes that use this material.
                //obs: foreach (RenderableMesh mesh in meshes)
                for (int meshNum = 0; meshNum < meshes.Count; meshNum++)
                {
                    RenderableMesh mesh = meshes[meshNum];
                    if (mesh.lastFrameRenderMatricesAndAlpha.Count > 0)
                    {
                        mesh.Render();
                    }
                }         // for (meshNum)
            }             // Render()
Example #10
0
            /// <summary>
            /// Render all meshes that use this material.
            /// This method is only called if we got any meshes to render,
            /// which is determinated if NumberOfRenderMeshes is greater 0.
            /// </summary>
            public void Render()
            {
                // Set material settings. We don't have to update the shader here,
                // it will be done in RenderableMesh.Render anyway because of
                // updating the world matrix!
                ShaderEffect.normalMapping.SetParametersOptimized(material);
                // Set vertex declaration
                //always true: if (meshes.Count > 0)

                // Enable alpha if this material uses alpha
                if (material.HasAlpha)
                {
                    //TODO: AlphaTestEffect
                    //BaseGame.Device.RenderState.AlphaTestEnable = true;
                    //BaseGame.Device.RenderState.ReferenceAlpha = 128;

                    // Make 2sided, we use alpha mainly for our palms.
                    BaseGame.Device.RasterizerState = RasterizerState.CullNone;
                }
                // Render all meshes that use this material.
                for (int meshNum = 0; meshNum < meshes.Count; meshNum++)
                {
                    RenderableMesh mesh = meshes[meshNum];
                    if (mesh.renderMatrices.Count > 0)
                    {
                        mesh.Render();
                    }
                }

                // Disable alpha testing again and restore culling
                if (material.HasAlpha)
                {
                    //TODO: AlphaTestEffect
                    //BaseGame.Device.RenderState.AlphaTestEnable = false;
                    BaseGame.Device.RasterizerState = RasterizerState.CullCounterClockwise;
                }
            }
Example #11
0
        private void DrawOverlay(RenderableMesh orignalMesh, RenderableMesh occluderMesh)
        {
            GL.PushAttrib(AttribMask.AllAttribBits);

            GL.Color4(1.0f, 1.0f, 1.0f, 1.0f);
            GL.Enable(EnableCap.Texture2D);
            GL.Enable(EnableCap.Blend);
            GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);

            GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
            GL.DepthFunc(DepthFunction.Lequal);

            QFont.Begin();

            float yOffset = 5;

            if (orignalMesh != null)
                PrintCode(String.Format("Orignal Triangles   : {0,5}", orignalMesh.Triangles), ref yOffset);
            if (occluderMesh != null)
                PrintCode(String.Format("Occluder Triangles  : {0,5}", occluderMesh.Triangles), ref yOffset);

            PrintCode(String.Format("Occluder Levels     : {0,5}", m_visualizedMaxLevel), ref yOffset);
            if (m_operations.Context.VoxelizationOutput != null)
            {
                PrintCode(String.Format("Volume Coverage     : {0,5:0.##}%", (100 * m_operations.Context.VoxelizationOutput.VolumeCoverage)), ref yOffset);
                PrintCode(String.Format("Silhouette Coverage : {0,5:0.##}%", (100 * m_operations.Context.VoxelizationOutput.SilhouetteCoverage)), ref yOffset);
                PrintCode(String.Format("Time Taken          : {0,5:0.##} seconds", m_operations.Context.VoxelizationOutput.TimeTaken.TotalSeconds), ref yOffset);
            }

            QFont.End();

            GL.PopAttrib();
        }
Example #12
0
        /// <summary>
        /// Add model mesh part with the used effect to our sortedMeshes list.
        /// Neither the model mesh part nor the effect is directly used,
        /// we will extract all data from the model and only render the
        /// index and vertex buffers later.
        /// The model mesh part must use the TangentVertex format.
        /// </summary>
        /// <param name="vertexBuffer">Vertex buffer</param>
        /// <param name="indexBuffer">Index buffer</param>
        /// <param name="part">Part</param>
        /// <param name="effect">Effect</param>
        /// <returns>Renderable mesh</returns>
        public RenderableMesh Add(VertexBuffer vertexBuffer,
                                  IndexBuffer indexBuffer, ModelMeshPart part, Effect effect)
        {
            string techniqueName = effect.CurrentTechnique.Name;

            // Does this technique already exists?
            MeshesPerMaterialPerTechniques foundList = null;

            for (int listNum = 0; listNum < sortedMeshes.Count; listNum++)
            {
                MeshesPerMaterialPerTechniques list = sortedMeshes[listNum];

                if (list.technique.Name == techniqueName)
                {
                    foundList = list;
                    break;
                }
            }

            // Did not found list? Create new one
            if (foundList == null)
            {
                foundList = new MeshesPerMaterialPerTechniques(
                    ShaderEffect.normalMapping.GetTechnique(techniqueName));
                sortedMeshes.Add(foundList);
            }

            // Create new material from the current effect parameters.
            // This will create duplicate materials if the same material is used
            // multiple times, we check this later.
            Material material = new Material(effect);

            // Search for material inside foundList.
            for (int innerListNum = 0; innerListNum <
                 foundList.meshesPerMaterials.Count; innerListNum++)
            {
                MeshesPerMaterial innerList =
                    foundList.meshesPerMaterials[innerListNum];

                // Check if this is the same material and we can use it instead.
                // For our purposes it is sufficiant if we check textures and colors.
                if (innerList.material.diffuseTexture == material.diffuseTexture &&
                    innerList.material.normalTexture == material.normalTexture &&
                    innerList.material.ambientColor == material.ambientColor &&
                    innerList.material.diffuseColor == material.diffuseColor &&
                    innerList.material.specularColor == material.specularColor &&
                    innerList.material.specularPower == material.specularPower)
                {
                    // Reuse this material and quit this search
                    material = innerList.material;
                    break;
                }
            }

            // Build new RenderableMesh object
            RenderableMesh mesh = new RenderableMesh(
                vertexBuffer, indexBuffer, material, foundList.technique,
                ShaderEffect.normalMapping.WorldParameter,
                part.VertexDeclaration,
                part.StreamOffset, part.VertexStride, part.BaseVertex,
                part.NumVertices, part.StartIndex, part.PrimitiveCount);

            foundList.Add(mesh);
            return(mesh);
        }
        /// <summary>
        /// Add model mesh part with the used effect to our sortedMeshes list.
        /// Neither the model mesh part nor the effect is directly used,
        /// we will extract all data from the model and only render the
        /// index and vertex buffers later.
        /// The model mesh part must use the TangentVertex format.
        /// </summary>
        /// <param name="vertexBuffer">Vertex buffer</param>
        /// <param name="indexBuffer">Index buffer</param>
        /// <param name="part">Part</param>
        /// <param name="effect">Effect</param>
        /// <returns>Renderable mesh</returns>
        public RenderableMesh Add(VertexBuffer vertexBuffer,
                                  IndexBuffer indexBuffer, ModelMeshPart part, Effect effect)
        {
            string techniqueName = effect.CurrentTechnique.Name;

            // Does this technique already exists?
            MeshesPerMaterialPerTechniques foundList = null;

            //obs: foreach (MeshesPerMaterialPerTechniques list in sortedMeshes)
            for (int listNum = 0; listNum < sortedMeshes.Count; listNum++)
            {
                MeshesPerMaterialPerTechniques list = sortedMeshes[listNum];

                if (list.technique != null &&
                    list.technique.Name == techniqueName)
                {
                    foundList = list;
                    break;
                }         // if (list.technique.Name)
            }             // for (listNum)

            // Did not found list? Create new one
            if (foundList == null)
            {
                EffectTechnique technique =
                    BaseGame.ParallaxShader.GetTechnique(techniqueName);

                // Make sure we always have a valid technique
                if (technique == null)
                {
                    if (BaseGame.CanUsePS20)
                    {
                        techniqueName = "Diffuse20";                        //"Specular20";
                    }
                    else
                    {
                        techniqueName = "Diffuse";                        //"Specular";
                    }
                    technique = BaseGame.ParallaxShader.GetTechnique(techniqueName);
                }                 // if

                foundList = new MeshesPerMaterialPerTechniques(technique);
                sortedMeshes.Add(foundList);
            }             // if (foundList)

            // Create new material from the current effect parameters.
            // This will create duplicate materials if the same material is used
            // multiple times, we check this later.
            Material material = new Material(effect);

            // Search for material inside foundList.
            //obs: foreach (MeshesPerMaterial innerList in foundList.meshesPerMaterials)
            for (int innerListNum = 0; innerListNum <
                 foundList.meshesPerMaterials.Count; innerListNum++)
            {
                MeshesPerMaterial innerList =
                    foundList.meshesPerMaterials[innerListNum];

                // Check if this is the same material and we can use it instead.
                // For our purposes it is sufficiant if we check textures and colors.
                if (innerList.material.diffuseTexture == material.diffuseTexture &&
                    innerList.material.normalTexture == material.normalTexture &&
                    innerList.material.ambientColor == material.ambientColor &&
                    innerList.material.diffuseColor == material.diffuseColor &&
                    innerList.material.specularColor == material.specularColor &&
                    innerList.material.specularPower == material.specularPower)
                {
                    // Reuse this material and quit this search
                    material = innerList.material;
                    break;
                }         // if (innerList.material.diffuseTexture)
            }             // foreach (innerList)

            // Build new RenderableMesh object
            RenderableMesh mesh = new RenderableMesh(
                vertexBuffer, indexBuffer, material, foundList.technique,
                part.VertexDeclaration,
                part.StreamOffset, part.VertexStride, part.BaseVertex,
                part.NumVertices, part.StartIndex, part.PrimitiveCount);

            foundList.Add(mesh);
            return(mesh);
        }         // Add(vertexBuffer, indexBuffer, part)
        private void BuildRenderableMeshes(Model model)
        {
            List<short> indices = new List<short>();
            List<InstancedVertexPositionNormalTextureBumpSkin> vertices = new List<InstancedVertexPositionNormalTextureBumpSkin>();
            Dictionary<int, int> indexRemap = new Dictionary<int, int>();

            // Get the model transforms for baking down vertices into object space (XNA Models are stored in mesh space).
            Matrix[] boneArray = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(boneArray);


            foreach (ModelMesh modelMesh in model.Meshes)
            {
                Debug.WriteLine("Building " + modelMesh.Name);
                Matrix meshToObject = boneArray[modelMesh.ParentBone.Index];

                for(int p=0;p<modelMesh.MeshParts.Count;p++)
                {
                    ModelMeshPart modelMeshPart = modelMesh.MeshParts[p];

                    int vertexCount = modelMeshPart.VertexBuffer.VertexCount;
                    int indexCount = modelMeshPart.IndexBuffer.IndexCount;

                    indexRemap.Clear();

                    vertices.Clear();
                    indices.Clear();

                    // Create a material for this meshpart
                    // TODO: Group data by effects 
                    DeferredSasEffect partEffect = (DeferredSasEffect)_sourceEffect.Clone();
                    partEffect.Parameters["AnimationTexture"].SetValue(_animationTexture);
                    partEffect.Parameters["BoneDelta"].SetValue(1f / _animationTexture.Width);
                    partEffect.Parameters["RowDelta"].SetValue(1f / _animationTexture.Height);
                    DeferredObjectEffect effect = (DeferredObjectEffect) modelMeshPart.Effect;
                    partEffect.Parameters["DiffuseTexture"].SetValue(effect.DiffuseMapTexture);                    

                    short[] sourceIndices = new short[modelMeshPart.PrimitiveCount*3];
                    modelMeshPart.IndexBuffer.GetData<short>(modelMeshPart.StartIndex*2,sourceIndices,0,modelMeshPart.PrimitiveCount*3);

                    InstancedVertexPositionNormalTextureBumpSkin[] sourceVertices = new InstancedVertexPositionNormalTextureBumpSkin[modelMeshPart.NumVertices];
                    modelMeshPart.VertexBuffer.GetData<InstancedVertexPositionNormalTextureBumpSkin>(modelMeshPart.VertexOffset * modelMeshPart.VertexBuffer.VertexDeclaration.VertexStride, sourceVertices, 0, modelMeshPart.NumVertices, modelMeshPart.VertexBuffer.VertexDeclaration.VertexStride);

                    for (int instance = 0; instance < _maxInstances; instance++)
                    {
                        for (int i = 0; i < sourceIndices.Length; i++)
                        {
                            indices.Add((short) ((sourceIndices[i]) + (instance * sourceVertices.Length))) ;
                        }

                        for (int i = 0; i < sourceVertices.Length; i++)
                        {
                            sourceVertices[i].TextureCoordinate2 = new Vector2(instance, 0);
                            vertices.Add(sourceVertices[i]);
                        }
                    }

                    VertexBuffer vertexBuffer = new VertexBuffer(_graphicsDevice, typeof(InstancedVertexPositionNormalTextureBumpSkin), vertices.Count, BufferUsage.None);
                    vertexBuffer.SetData<InstancedVertexPositionNormalTextureBumpSkin>(vertices.ToArray());
                    IndexBuffer indexBuffer = new IndexBuffer(_graphicsDevice, IndexElementSize.SixteenBits, indices.Count, BufferUsage.None);
                    indexBuffer.SetData<short>(indices.ToArray());

                    RenderableMesh renderableMesh = new RenderableMesh();
                    renderableMesh.Build(this, partEffect, Matrix.Identity, _boundingSphere, _boundingBox,
                        indexBuffer, vertexBuffer, 0, PrimitiveType.TriangleList, indexBuffer.IndexCount / 3, 0, vertexBuffer.VertexCount, 0, true);
                    base.Add(renderableMesh);

                }
            }
        }
            /// <summary>
            /// Adds a renderable mesh using this technique.
            /// </summary>
            /// <param name="addMesh">Add mesh</param>
            public void Add(RenderableMesh addMesh)
            {
                // Make sure this mesh uses the correct material
                if (addMesh.usedTechnique != technique)
                    throw new Exception("Invalid technique, to add a mesh to "+
                        "MeshesPerMaterialPerTechniques it must use the specified "+
                        "technique="+technique.Name);

                // Search for the used material, maybe we have it already in list.
                //obs: foreach (MeshesPerMaterial list in meshesPerMaterials)
                for (int listNum = 0; listNum < meshesPerMaterials.Count; listNum++)
                {
                    MeshesPerMaterial existingList = meshesPerMaterials[listNum];
                    if (existingList.material == addMesh.material)
                    {
                        // Just add
                        existingList.Add(addMesh);
                        return;
                    } // if (existingList.material)
                } // for (listNum)

                // Not found, create new list and add mesh there.
                MeshesPerMaterial newList = new MeshesPerMaterial(addMesh.material);
                newList.Add(addMesh);
                meshesPerMaterials.Add(newList);
            }
        long MeasureOccluderOcclusion(SilhouetteOcclusionValidator sov, VoxelizationInput input, List<AABBi> occluderBounds)
        {
            Mesh mesh = BuildMeshFromBoxes(input, occluderBounds);
            RenderableMesh renderable = new RenderableMesh(mesh, true);

            long sideCoverage, topCoverage;
            sov.ComputeCoverage(renderable, input.Octree.MeshBounds, out sideCoverage, out topCoverage);

            renderable.Dispose();

            return sideCoverage + topCoverage;
        }
Example #17
0
        private void BuildRenderableMeshes(Model model)
        {
            List <short> indices = new List <short>();
            List <InstancedVertexPositionNormalTextureBumpSkin> vertices = new List <InstancedVertexPositionNormalTextureBumpSkin>();
            Dictionary <int, int> indexRemap = new Dictionary <int, int>();

            // Get the model transforms for baking down vertices into object space (XNA Models are stored in mesh space).
            Matrix[] boneArray = new Matrix[model.Bones.Count];
            model.CopyAbsoluteBoneTransformsTo(boneArray);


            foreach (ModelMesh modelMesh in model.Meshes)
            {
                Debug.WriteLine("Building " + modelMesh.Name);
                Matrix meshToObject = boneArray[modelMesh.ParentBone.Index];

                for (int p = 0; p < modelMesh.MeshParts.Count; p++)
                {
                    ModelMeshPart modelMeshPart = modelMesh.MeshParts[p];

                    int vertexCount = modelMeshPart.VertexBuffer.VertexCount;
                    int indexCount  = modelMeshPart.IndexBuffer.IndexCount;

                    indexRemap.Clear();

                    vertices.Clear();
                    indices.Clear();

                    // Create a material for this meshpart
                    // TODO: Group data by effects
                    DeferredSasEffect partEffect = (DeferredSasEffect)_sourceEffect.Clone();
                    partEffect.Parameters["AnimationTexture"].SetValue(_animationTexture);
                    partEffect.Parameters["BoneDelta"].SetValue(1f / _animationTexture.Width);
                    partEffect.Parameters["RowDelta"].SetValue(1f / _animationTexture.Height);
                    DeferredObjectEffect effect = (DeferredObjectEffect)modelMeshPart.Effect;
                    partEffect.Parameters["DiffuseTexture"].SetValue(effect.DiffuseMapTexture);

                    short[] sourceIndices = new short[modelMeshPart.PrimitiveCount * 3];
                    modelMeshPart.IndexBuffer.GetData <short>(modelMeshPart.StartIndex * 2, sourceIndices, 0, modelMeshPart.PrimitiveCount * 3);

                    InstancedVertexPositionNormalTextureBumpSkin[] sourceVertices = new InstancedVertexPositionNormalTextureBumpSkin[modelMeshPart.NumVertices];
                    modelMeshPart.VertexBuffer.GetData <InstancedVertexPositionNormalTextureBumpSkin>(modelMeshPart.VertexOffset * modelMeshPart.VertexBuffer.VertexDeclaration.VertexStride, sourceVertices, 0, modelMeshPart.NumVertices, modelMeshPart.VertexBuffer.VertexDeclaration.VertexStride);

                    for (int instance = 0; instance < _maxInstances; instance++)
                    {
                        for (int i = 0; i < sourceIndices.Length; i++)
                        {
                            indices.Add((short)((sourceIndices[i]) + (instance * sourceVertices.Length)));
                        }

                        for (int i = 0; i < sourceVertices.Length; i++)
                        {
                            sourceVertices[i].TextureCoordinate2 = new Vector2(instance, 0);
                            vertices.Add(sourceVertices[i]);
                        }
                    }

                    VertexBuffer vertexBuffer = new VertexBuffer(_graphicsDevice, typeof(InstancedVertexPositionNormalTextureBumpSkin), vertices.Count, BufferUsage.None);
                    vertexBuffer.SetData <InstancedVertexPositionNormalTextureBumpSkin>(vertices.ToArray());
                    IndexBuffer indexBuffer = new IndexBuffer(_graphicsDevice, IndexElementSize.SixteenBits, indices.Count, BufferUsage.None);
                    indexBuffer.SetData <short>(indices.ToArray());

                    RenderableMesh renderableMesh = new RenderableMesh();
                    renderableMesh.Build(this, partEffect, Matrix.Identity, _boundingSphere, _boundingBox,
                                         indexBuffer, vertexBuffer, 0, PrimitiveType.TriangleList, indexBuffer.IndexCount / 3, 0, vertexBuffer.VertexCount, 0, true);
                    base.Add(renderableMesh);
                }
            }
        }
            /// <summary>
            /// Adds a renderable mesh using this material.
            /// </summary>
            /// <param name="addMesh">Add mesh</param>
            public void Add(RenderableMesh addMesh)
            {
                // Make sure this mesh uses the correct material
                if (addMesh.material != material)
                    throw new Exception("Invalid material, to add a mesh to "+
                        "MeshesPerMaterial it must use the specified material="+
                        material);

                meshes.Add(addMesh);
            }
        private void RenderView(Matrix4 worldViewMatrix, Matrix4 projMatrix, RenderableMesh mesh, int occlusionQueryHandle)
        {
            // Setup VBO state
            GL.EnableClientState(ArrayCap.VertexArray);
            GL.EnableClientState(ArrayCap.IndexArray);

            GL.Enable(EnableCap.StencilTest);
            GL.StencilFunc(StencilFunction.Always, 1, 1);
            GL.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Replace);

            GL.PushAttrib(AttribMask.ViewportBit);
            GL.Viewport(0, 0, m_pixelWidth, m_pixelHeight);

            GL.Ext.BindFramebuffer(FramebufferTarget.FramebufferExt, m_fboHandle);

            // since there's only 1 Color buffer attached this is not explicitly required
            GL.DrawBuffer((DrawBufferMode)FramebufferAttachment.ColorAttachment0Ext);
            GL.Ext.FramebufferTexture2D(FramebufferTarget.FramebufferExt, FramebufferAttachment.ColorAttachment0Ext, TextureTarget.Texture2D, m_colorTextureHandle, 0);
            GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, FramebufferAttachment.DepthAttachmentExt, RenderbufferTarget.RenderbufferExt, m_renderbufferHandle);
            GL.Ext.FramebufferRenderbuffer(FramebufferTarget.FramebufferExt, FramebufferAttachment.StencilAttachmentExt, RenderbufferTarget.RenderbufferExt, m_renderbufferHandle);

            GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit);

            GL.PushMatrix();

            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadMatrix(ref worldViewMatrix);
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadMatrix(ref projMatrix);

            GL.Enable(EnableCap.DepthTest);
            GL.Disable(EnableCap.CullFace);

            var effect = new Material();
            effect.ShaderHandle = 0;
            effect.ShowLines = false;

            GL.Color4(1.0f, 1.0f, 1.0f, 1.0f);
            mesh.Render(effect);

            GL.PopMatrix();

            GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);

            // Render a quad with stencil test turned on, this will give me an accurate number of pixels rendered for
            // the object.

            GL.StencilFunc(StencilFunction.Equal, 1, 1);
            GL.StencilOp(StencilOp.Keep, StencilOp.Keep, StencilOp.Keep);

            GL.MatrixMode(MatrixMode.Modelview);
            GL.LoadIdentity();
            GL.MatrixMode(MatrixMode.Projection);
            GL.LoadIdentity();

            GL.Ortho(0, 1, 1, 0, -1, 1);

            GL.Disable(EnableCap.DepthTest);

            GL.BeginQuery(QueryTarget.SamplesPassed, occlusionQueryHandle);

            GL.Color4(1.0f, 1.0f, 1.0f, 1.0f);
            GL.Begin(BeginMode.Quads);
            GL.TexCoord2(0f, 1f); GL.Vertex2(0f, 0f);
            GL.TexCoord2(1f, 1f); GL.Vertex2(1f, 0f);
            GL.TexCoord2(1f, 0f); GL.Vertex2(1f, 1f);
            GL.TexCoord2(0f, 0f); GL.Vertex2(0f, 1f);
            GL.End();

            GL.EndQuery(QueryTarget.SamplesPassed);

            GL.Enable(EnableCap.DepthTest);
            GL.Disable(EnableCap.StencilTest);

            GL.PopAttrib();
        }
        /// <summary>
        /// Add model mesh part with the used effect to our sortedMeshes list.
        /// Neither the model mesh part nor the effect is directly used,
        /// we will extract all data from the model and only render the
        /// index and vertex buffers later.
        /// The model mesh part must use the TangentVertex format.
        /// </summary>
        /// <param name="vertexBuffer">Vertex buffer</param>
        /// <param name="indexBuffer">Index buffer</param>
        /// <param name="part">Part</param>
        /// <param name="effect">Effect</param>
        /// <returns>Renderable mesh</returns>
        public RenderableMesh Add(VertexBuffer vertexBuffer,
			IndexBuffer indexBuffer, ModelMeshPart part, Effect effect)
        {
            string techniqueName = effect.CurrentTechnique.Name;

            // Does this technique already exists?
            MeshesPerMaterialPerTechniques foundList = null;
            //obs: foreach (MeshesPerMaterialPerTechniques list in sortedMeshes)
            for (int listNum = 0; listNum < sortedMeshes.Count; listNum++)
            {
                MeshesPerMaterialPerTechniques list = sortedMeshes[listNum];

                if (list.technique != null &&
                    list.technique.Name == techniqueName)
                {
                    foundList = list;
                    break;
                } // if (list.technique.Name)
            } // for (listNum)

            // Did not found list? Create new one
            if (foundList == null)
            {
                EffectTechnique technique =
                    BaseGame.ParallaxShader.GetTechnique(techniqueName);

                // Make sure we always have a valid technique
                if (technique == null)
                {
                    if (BaseGame.CanUsePS20)
                        techniqueName = "Diffuse20";//"Specular20";
                    else
                        techniqueName = "Diffuse";//"Specular";
                    technique = BaseGame.ParallaxShader.GetTechnique(techniqueName);
                } // if

                foundList = new MeshesPerMaterialPerTechniques(technique);
                sortedMeshes.Add(foundList);
            } // if (foundList)

            // Create new material from the current effect parameters.
            // This will create duplicate materials if the same material is used
            // multiple times, we check this later.
            Material material = new Material(effect);

            // Search for material inside foundList.
            //obs: foreach (MeshesPerMaterial innerList in foundList.meshesPerMaterials)
            for (int innerListNum = 0; innerListNum <
                foundList.meshesPerMaterials.Count; innerListNum++)
            {
                MeshesPerMaterial innerList =
                    foundList.meshesPerMaterials[innerListNum];

                // Check if this is the same material and we can use it instead.
                // For our purposes it is sufficiant if we check textures and colors.
                if (innerList.material.diffuseTexture == material.diffuseTexture &&
                    innerList.material.normalTexture == material.normalTexture &&
                    innerList.material.ambientColor == material.ambientColor &&
                    innerList.material.diffuseColor == material.diffuseColor &&
                    innerList.material.specularColor == material.specularColor &&
                    innerList.material.specularPower == material.specularPower)
                {
                    // Reuse this material and quit this search
                    material = innerList.material;
                    break;
                } // if (innerList.material.diffuseTexture)
            } // foreach (innerList)

            // Build new RenderableMesh object
            RenderableMesh mesh = new RenderableMesh(
                vertexBuffer, indexBuffer, material, foundList.technique,
                part.VertexDeclaration,
                part.StreamOffset, part.VertexStride, part.BaseVertex,
                part.NumVertices, part.StartIndex, part.PrimitiveCount);
            foundList.Add(mesh);
            return mesh;
        }
        /// <summary>
        /// Add model mesh part with the used effect to our sortedMeshes list.
        /// Neither the model mesh part nor the effect is directly used,
        /// we will extract all data from the model and only render the
        /// index and vertex buffers later.
        /// The model mesh part must use the TangentVertex format.
        /// </summary>
        /// <param name="vertexBuffer">Vertex buffer</param>
        /// <param name="indexBuffer">Index buffer</param>
        /// <param name="part">Part</param>
        /// <param name="effect">Effect</param>
        /// <returns>Renderable mesh</returns>
        public RenderableMesh Add(VertexBuffer vertexBuffer,
            IndexBuffer indexBuffer, ModelMeshPart part, Effect effect)
        {
            string techniqueName = effect.CurrentTechnique.Name;

            // Does this technique already exists?
            MeshesPerMaterialPerTechniques foundList = null;
            for (int listNum = 0; listNum < sortedMeshes.Count; listNum++)
            {
                MeshesPerMaterialPerTechniques list = sortedMeshes[listNum];

                if (list.technique.Name == techniqueName)
                {
                    foundList = list;
                    break;
                }
            }

            // Did not found list? Create new one
            if (foundList == null)
            {
                foundList = new MeshesPerMaterialPerTechniques(
                    ShaderEffect.normalMapping.GetTechnique(techniqueName));
                sortedMeshes.Add(foundList);
            }

            // Create new material from the current effect parameters.
            // This will create duplicate materials if the same material is used
            // multiple times, we check this later.
            Material material = new Material(effect);

            // Search for material inside foundList.
            for (int innerListNum = 0; innerListNum <
                foundList.meshesPerMaterials.Count; innerListNum++)
            {
                MeshesPerMaterial innerList =
                    foundList.meshesPerMaterials[innerListNum];

                // Check if this is the same material and we can use it instead.
                // For our purposes it is sufficiant if we check textures and colors.
                if (innerList.material.diffuseTexture == material.diffuseTexture &&
                    innerList.material.normalTexture == material.normalTexture &&
                    innerList.material.ambientColor == material.ambientColor &&
                    innerList.material.diffuseColor == material.diffuseColor &&
                    innerList.material.specularColor == material.specularColor &&
                    innerList.material.specularPower == material.specularPower)
                {
                    // Reuse this material and quit this search
                    material = innerList.material;
                    break;
                }
            }

            // Build new RenderableMesh object
            RenderableMesh mesh = new RenderableMesh(
                vertexBuffer, indexBuffer, material, foundList.technique,
                ShaderEffect.normalMapping.WorldParameter, part.VertexOffset,
                part.NumVertices, part.StartIndex, part.PrimitiveCount);
            foundList.Add(mesh);
            return mesh;
        }