Manages and draws instanced models.
Inheritance: ModelDrawer
Esempio n. 1
0
        /// <summary>
        /// Removes a display object from the batch.
        /// </summary>
        /// <param name="displayObject">Display object to remove.</param>
        /// <param name="drawer">Instanced model drawer doing the removal.</param>
        public void Remove(ModelDisplayObjectBase displayObject, InstancedModelDrawer drawer)
        {
            //Modify vertex buffer
            var newVertices = new VertexPositionNormalTexture[vertices.Length - displayObject.BatchInformation.VertexCount];

            //Copy the first part back (before the display object)
            Array.Copy(vertices, 0, newVertices, 0, displayObject.BatchInformation.BaseVertexBufferIndex);
            //Copy the second part back (after the display object)
            Array.Copy(vertices, displayObject.BatchInformation.BaseVertexBufferIndex + displayObject.BatchInformation.VertexCount,
                       newVertices, displayObject.BatchInformation.BaseVertexBufferIndex,
                       vertices.Length - (displayObject.BatchInformation.BaseVertexBufferIndex + displayObject.BatchInformation.VertexCount));
            vertices = newVertices;

            //Modify index buffer
            var newIndices = new ushort[indices.Length - displayObject.BatchInformation.IndexCount];

            //Copy the first part back (before the display object)
            Array.Copy(indices, 0, newIndices, 0, displayObject.BatchInformation.BaseIndexBufferIndex);
            //Copy the second part back (after the display object)
            Array.Copy(indices, displayObject.BatchInformation.BaseIndexBufferIndex + displayObject.BatchInformation.IndexCount,
                       newIndices, displayObject.BatchInformation.BaseIndexBufferIndex,
                       indices.Length - (displayObject.BatchInformation.BaseIndexBufferIndex + displayObject.BatchInformation.IndexCount));
            indices = newIndices;
            //The index buffer's data is now wrong though.  We deleted a bunch of vertices.
            //So go through the index buffer starting at the point of deletion and decrease the values appropriately.
            for (int i = displayObject.BatchInformation.BaseIndexBufferIndex; i < indices.Length; i++)
            {
                indices[i] -= (ushort)displayObject.BatchInformation.VertexCount;
            }

            //Modify instancing indices
            var newInstancingIndices = new float[instancingIndices.Length - displayObject.BatchInformation.VertexCount];

            //Copy the first part back (before the display object)
            Array.Copy(instancingIndices, 0, newInstancingIndices, 0, displayObject.BatchInformation.BaseVertexBufferIndex);
            //Copy the second part back (after the display object)
            Array.Copy(instancingIndices, displayObject.BatchInformation.BaseVertexBufferIndex + displayObject.BatchInformation.VertexCount,
                       newInstancingIndices, displayObject.BatchInformation.BaseVertexBufferIndex,
                       instancingIndices.Length - (displayObject.BatchInformation.BaseVertexBufferIndex + displayObject.BatchInformation.VertexCount));
            instancingIndices = newInstancingIndices;
            //Like with the index buffer, go through the buffer starting at the point of deletion and decrease the values appropriately.
            for (int i = displayObject.BatchInformation.BaseVertexBufferIndex; i < instancingIndices.Length; i++)
            {
                instancingIndices[i]--;
            }

            myDisplayObjects.Remove(displayObject);
            // Tell ModelDisplayObject that it got removed (batch, indices).
            displayObject.ClearBatchReferences();

            vertexBuffer = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
            vertexBuffer.SetData(vertices);
            instancingBuffer = new VertexBuffer(graphicsDevice, drawer.instancingVertexDeclaration, instancingIndices.Length, BufferUsage.WriteOnly);
            instancingBuffer.SetData(instancingIndices);
            bindings    = new VertexBufferBinding[] { vertexBuffer, instancingBuffer };
            indexBuffer = new IndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, indices.Length, BufferUsage.WriteOnly);
            indexBuffer.SetData(indices);
        }
Esempio n. 2
0
        /// <summary>
        /// Removes a display object from the batch.
        /// </summary>
        /// <param name="displayObject">Display object to remove.</param>
        /// <param name="drawer">Instanced model drawer doing the removal.</param>
        public unsafe void Remove(ModelDisplayObject displayObject, InstancedModelDrawer drawer)
        {
            //Copy the end of the list over the top of the  part back (after the display object)
            var vertexCopySource = displayObject.BatchInformation.BaseVertexBufferIndex + displayObject.BatchInformation.VertexCount;
            var vertexCopyTarget = displayObject.BatchInformation.BaseVertexBufferIndex;
            var vertexCopyLength = vertexCount - vertexCopySource;

            Array.Copy(vertices, vertexCopySource, vertices, vertexCopyTarget, vertexCopyLength);
            Array.Copy(instancedVertices, vertexCopySource, instancedVertices, vertexCopyTarget, vertexCopyLength);
            vertexCount -= displayObject.BatchInformation.VertexCount;

            //Copy the first part back (before the display object)
            var indexCopySource = displayObject.BatchInformation.BaseIndexBufferIndex + displayObject.BatchInformation.IndexCount;
            var indexCopyTarget = displayObject.BatchInformation.BaseIndexBufferIndex;
            var indexCopyLength = indexCount - indexCopySource;

            Array.Copy(indices, indexCopySource, indices, indexCopyTarget, indexCopyLength);
            indexCount -= displayObject.BatchInformation.IndexCount;

            //The index buffer's data is now wrong. We deleted a bunch of vertices.
            //So go through the index buffer starting at the point of deletion and decrease the values appropriately.
            for (int i = displayObject.BatchInformation.BaseIndexBufferIndex; i < indexCount; i++)
            {
                indices[i] -= (ushort)displayObject.BatchInformation.VertexCount;
            }

            //Like with the index buffer, go through the buffer starting at the point of deletion and decrease the instance index values.
            for (int i = displayObject.BatchInformation.BaseVertexBufferIndex; i < vertexCount; i++)
            {
                instancedVertices[i].InstanceIndex--;
            }

            displayObjects.Remove(displayObject);
            //Move the subsequent display objects list indices and base vertices/indices.
            for (int i = displayObject.BatchInformation.BatchListIndex; i < DisplayObjects.Count; i++)
            {
                DisplayObjects[i].BatchInformation.BatchListIndex--;
                DisplayObjects[i].BatchInformation.BaseVertexBufferIndex -= displayObject.BatchInformation.VertexCount;
                DisplayObjects[i].BatchInformation.BaseIndexBufferIndex  -= displayObject.BatchInformation.IndexCount;
            }
            // Tell ModelDisplayObject that it got removed (batch, indices).
            var batchListIndex = displayObject.BatchInformation.BatchListIndex;

            displayObject.ClearBatchReferences();

            if (displayObjects.Count > 0 && batchListIndex < displayObjects.Count)
            {
                vertexBuffer.SetData(sizeof(VertexPositionNormalTexture) * vertexCopyTarget, vertices, vertexCopyTarget, vertexCopyLength, sizeof(VertexPositionNormalTexture));
                instancedBuffer.SetData(sizeof(InstancedVertex) * vertexCopyTarget, instancedVertices, vertexCopyTarget, vertexCopyLength, sizeof(InstancedVertex));
                indexBuffer.SetData(sizeof(ushort) * indexCopyTarget, indices, indexCopyTarget, indexCopyLength);
            }
        }
        /// <summary>
        /// Adds a display object to the batch.
        /// </summary>
        /// <param name="displayObject">Display object to add.</param>
        /// <param name="drawer">Drawer of the batch.</param>
        public bool Add(ModelDisplayObject displayObject, InstancedModelDrawer drawer)
        {
            //In theory, don't need to test for dupliate entries since batch.Add
            //should only be called through a InstancedModelDrawer's add (which checks beforehand).
            if (displayObjects.Count == MaximumObjectsPerBatch ||
                ((indices.Length / 3 + displayObject.GetTriangleCountEstimate()) > MaximumPrimitiveCountPerBatch &&
                 displayObjects.Count > 0))
            {
                return(false);
            }
            displayObjects.Add(displayObject);
            int instanceIndex = displayObjects.Count - 1;
            var textureIndex  = displayObject.TextureIndex;

            displayObject.GetVertexData(vertexList, indexList, this, (ushort)vertices.Length, indices.Length, instanceIndex);
            //Add the data to the batch.
            var newVertices = new VertexPositionNormalTexture[vertices.Length + vertexList.Count];

            vertices.CopyTo(newVertices, 0);
            vertexList.CopyTo(newVertices, vertices.Length);
            vertices = newVertices;

            var newIndices = new ushort[indices.Length + indexList.Count];

            indices.CopyTo(newIndices, 0);
            indexList.CopyTo(newIndices, indices.Length);
            indices = newIndices;

            var newInstancingVertices = new InstancedVertex[instancedVertices.Length + vertexList.Count];

            instancedVertices.CopyTo(newInstancingVertices, 0);
            for (int i = instancedVertices.Length; i < newInstancingVertices.Length; i++)
            {
                newInstancingVertices[i] = new InstancedVertex {
                    InstanceIndex = instanceIndex, TextureIndex = textureIndex
                }
            }
            ;
            instancedVertices = newInstancingVertices;

            vertexBuffer = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
            vertexBuffer.SetData(vertices);
            instancingBuffer = new VertexBuffer(graphicsDevice, InstancedVertex.VertexDeclaration, instancedVertices.Length, BufferUsage.WriteOnly);
            instancingBuffer.SetData(instancedVertices);
            bindings    = new VertexBufferBinding[] { vertexBuffer, instancingBuffer };
            indexBuffer = new IndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, indices.Length, BufferUsage.WriteOnly);
            indexBuffer.SetData(indices);

            vertexList.Clear();
            indexList.Clear();
            return(true);
        }
        /// <summary>
        /// Constructs a new demo.
        /// </summary>
        /// <param name="game">Game owning this demo.</param>
        public InverseKinematicsTestDemo(DemosGame game)
            : base(game)
        {
            cameraControl = new FreeCameraControlScheme(10, game.Camera, game);
            whitePixel = game.Content.Load<Texture2D>("whitePixel");
            game.Camera.Position = new Vector3(0, 3, 5);
            Box ground = new Box(new Vector3(0, 0, 0), 30, 1, 30);
            Space.Add(ground);
            Space.ForceUpdater.Gravity = new Vector3(0, -9.81f, 0);

            stateControlGroup = new StateControlGroup(game.Camera, controls);

            drawer = new InstancedModelDrawer(game);

            solver.ActiveSet.UseAutomass = true;
            solver.AutoscaleControlImpulses = true;
            solver.AutoscaleControlMaximumForce = float.MaxValue;
            solver.TimeStepDuration = .1f;
            solver.ControlIterationCount = 100;
            solver.FixerIterationCount = 10;
            solver.VelocitySubiterationCount = 3;

            BuildChain(new Vector3(-5, 2, 0));

            BuildStick(new Vector3(-10, 2, 0));

            BuildActionFigure(new Vector3(5, 6, -8));
            BuildActionFigure(new Vector3(5, 6, -3));
            BuildActionFigure(new Vector3(5, 6, 3));
            BuildActionFigure(new Vector3(5, 6, 8));

            BuildCyclicMesh(new Vector3(-5, 5, -5));

            //BuildJointTest(new Vector3(0, 5, 0));
            //BuildTinyTest(new Vector3(0, 15, 0));

            BuildRoboArmThing(new Vector3(0, 5, 0));

            BuildRing(new Vector3(0, 10, 8));

            //Create the display objects.
            Model cylinder = game.Content.Load<Model>("cylinder");
            for (int i = 0; i < bones.Count; i++)
            {
                var displayBone = new DisplayModel(cylinder, drawer);
                var completedBone = bones[i];
                completedBone.DisplayBone = displayBone;
                bones[i] = completedBone;
                drawer.Add(displayBone);
            }
        }
        /// <summary>
        /// Adds a display object to the batch.
        /// </summary>
        /// <param name="displayObject">Display object to add.</param>
        /// <param name="drawer">Drawer of the batch.</param>
        public bool Add(ModelDisplayObject displayObject, InstancedModelDrawer drawer)
        {
            //In theory, don't need to test for dupliate entries since batch.Add
            //should only be called through a InstancedModelDrawer's add (which checks beforehand).
            if (displayObjects.Count == MaximumObjectsPerBatch ||
                ((indices.Length / 3 + displayObject.GetTriangleCountEstimate()) > MaximumPrimitiveCountPerBatch &&
                 displayObjects.Count > 0))
                return false;
            displayObjects.Add(displayObject);
            int instanceIndex = displayObjects.Count - 1;
            var textureIndex = displayObject.TextureIndex;
            displayObject.GetVertexData(vertexList, indexList, this, (ushort)vertices.Length, indices.Length, instanceIndex);
            //Add the data to the batch.
            var newVertices = new VertexPositionNormalTexture[vertices.Length + vertexList.Count];
            vertices.CopyTo(newVertices, 0);
            vertexList.CopyTo(newVertices, vertices.Length);
            vertices = newVertices;

            var newIndices = new ushort[indices.Length + indexList.Count];
            indices.CopyTo(newIndices, 0);
            indexList.CopyTo(newIndices, indices.Length);
            indices = newIndices;

            var newInstancingVertices = new InstancedVertex[instancedVertices.Length + vertexList.Count];
            instancedVertices.CopyTo(newInstancingVertices, 0);
            for (int i = instancedVertices.Length; i < newInstancingVertices.Length; i++)
                newInstancingVertices[i] = new InstancedVertex { InstanceIndex = instanceIndex, TextureIndex = textureIndex };
            instancedVertices = newInstancingVertices;

            vertexBuffer = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
            vertexBuffer.SetData(vertices);
            instancingBuffer = new VertexBuffer(graphicsDevice, InstancedVertex.VertexDeclaration, instancedVertices.Length, BufferUsage.WriteOnly);
            instancingBuffer.SetData(instancedVertices);
            bindings = new VertexBufferBinding[] { vertexBuffer, instancingBuffer };
            indexBuffer = new IndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, indices.Length, BufferUsage.WriteOnly);
            indexBuffer.SetData(indices);

            vertexList.Clear();
            indexList.Clear();
            return true;
        }
Esempio n. 6
0
        /// <summary>
        /// Adds a display object to the batch.
        /// </summary>
        /// <param name="displayObject">Display object to add.</param>
        /// <param name="drawer">Drawer of the batch.</param>
        public unsafe bool Add(ModelDisplayObject displayObject, InstancedModelDrawer drawer)
        {
            //In theory, don't need to test for duplicate entries since batch.Add
            //should only be called through a InstancedModelDrawer's add (which checks beforehand).
            if (displayObjects.Count == MaximumObjectsPerBatch ||
                ((indexCount / 3 + displayObject.GetTriangleCountEstimate()) > MaximumPrimitiveCountPerBatch &&
                 displayObjects.Count > 0))
            {
                return(false);
            }
            displayObjects.Add(displayObject);
            int instanceIndex = displayObjects.Count - 1;
            var textureIndex  = displayObject.TextureIndex;

            //OUegheogh, this could just directly write into the batch's vertex/index cache rather than going through a list and recopy.
            displayObject.GetVertexData(vertexList, indexList, this, (ushort)vertexCount, indexCount, instanceIndex);
            vertexList.CopyTo(vertices, vertexCount);
            indexList.CopyTo(indices, indexCount);

            var newIndexCount  = indexCount + indexList.Count;
            var newVertexCount = vertexCount + vertexList.Count;

            for (int i = vertexCount; i < newVertexCount; i++)
            {
                instancedVertices[i] = new InstancedVertex {
                    InstanceIndex = instanceIndex, TextureIndex = textureIndex
                }
            }
            ;

            vertexBuffer.SetData(sizeof(VertexPositionNormalTexture) * vertexCount, vertices, vertexCount, vertexList.Count, sizeof(VertexPositionNormalTexture));
            instancedBuffer.SetData(sizeof(InstancedVertex) * vertexCount, instancedVertices, vertexCount, vertexList.Count, sizeof(InstancedVertex));
            indexBuffer.SetData(sizeof(ushort) * indexCount, indices, indexCount, indexList.Count);

            vertexCount = newVertexCount;
            indexCount  = newIndexCount;

            vertexList.Clear();
            indexList.Clear();
            return(true);
        }
        /// <summary>
        /// Removes a display object from the batch.
        /// </summary>
        /// <param name="displayObject">Display object to remove.</param>
        /// <param name="drawer">Instanced model drawer doing the removal.</param>
        public void Remove(ModelDisplayObject displayObject, InstancedModelDrawer drawer)
        {
            //Modify vertex buffer
            var newVertices = new VertexPositionNormalTexture[vertices.Length - displayObject.BatchInformation.VertexCount];
            //Copy the first part back (before the display object)
            Array.Copy(vertices, 0, newVertices, 0, displayObject.BatchInformation.BaseVertexBufferIndex);
            //Copy the second part back (after the display object)
            Array.Copy(vertices, displayObject.BatchInformation.BaseVertexBufferIndex + displayObject.BatchInformation.VertexCount,
                       newVertices, displayObject.BatchInformation.BaseVertexBufferIndex,
                       vertices.Length - (displayObject.BatchInformation.BaseVertexBufferIndex + displayObject.BatchInformation.VertexCount));
            vertices = newVertices;



            //Modify index buffer
            var newIndices = new ushort[indices.Length - displayObject.BatchInformation.IndexCount];
            //Copy the first part back (before the display object)
            Array.Copy(indices, 0, newIndices, 0, displayObject.BatchInformation.BaseIndexBufferIndex);
            //Copy the second part back (after the display object)
            Array.Copy(indices, displayObject.BatchInformation.BaseIndexBufferIndex + displayObject.BatchInformation.IndexCount,
                       newIndices, displayObject.BatchInformation.BaseIndexBufferIndex,
                       indices.Length - (displayObject.BatchInformation.BaseIndexBufferIndex + displayObject.BatchInformation.IndexCount));
            indices = newIndices;
            //The index buffer's data is now wrong though.  We deleted a bunch of vertices.
            //So go through the index buffer starting at the point of deletion and decrease the values appropriately.
            for (int i = displayObject.BatchInformation.BaseIndexBufferIndex; i < indices.Length; i++)
                indices[i] -= (ushort)displayObject.BatchInformation.VertexCount;

            //Modify instancing indices
            var newInstancedVertices = new InstancedVertex[instancedVertices.Length - displayObject.BatchInformation.VertexCount];
            //Copy the first part back (before the display object)
            Array.Copy(instancedVertices, 0, newInstancedVertices, 0, displayObject.BatchInformation.BaseVertexBufferIndex);
            //Copy the second part back (after the display object)
            Array.Copy(instancedVertices, displayObject.BatchInformation.BaseVertexBufferIndex + displayObject.BatchInformation.VertexCount,
                       newInstancedVertices, displayObject.BatchInformation.BaseVertexBufferIndex,
                       instancedVertices.Length - (displayObject.BatchInformation.BaseVertexBufferIndex + displayObject.BatchInformation.VertexCount));
            instancedVertices = newInstancedVertices;
            //Like with the index buffer, go through the buffer starting at the point of deletion and decrease the values appropriately.
            for (int i = displayObject.BatchInformation.BaseVertexBufferIndex; i < instancedVertices.Length; i++)
                instancedVertices[i].InstanceIndex--;

            displayObjects.Remove(displayObject);
            //Move the subsequent display objects list indices and base vertices/indices.
            for (int i = displayObject.BatchInformation.BatchListIndex; i < DisplayObjects.Count; i++)
            {
                DisplayObjects[i].BatchInformation.BatchListIndex--;
                DisplayObjects[i].BatchInformation.BaseVertexBufferIndex -= displayObject.BatchInformation.VertexCount;
                DisplayObjects[i].BatchInformation.BaseIndexBufferIndex -= displayObject.BatchInformation.IndexCount;
            }
            // Tell ModelDisplayObject that it got removed (batch, indices).
            displayObject.ClearBatchReferences();


            //If there weren't any vertices, this batch is about to die.
            if (displayObjects.Count > 0)
            {
                vertexBuffer = new VertexBuffer(graphicsDevice, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
                vertexBuffer.SetData(vertices);

                instancingBuffer = new VertexBuffer(graphicsDevice, InstancedVertex.VertexDeclaration, instancedVertices.Length, BufferUsage.WriteOnly);
                instancingBuffer.SetData(instancedVertices);

                indexBuffer = new IndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, indices.Length, BufferUsage.WriteOnly);
                indexBuffer.SetData(indices);

                bindings = new VertexBufferBinding[] { vertexBuffer, instancingBuffer };
            }
        }
Esempio n. 8
0
        protected override void Initialize()
        {
            camera = new Camera();
            int midX = GraphicsDeviceManager.DefaultBackBufferHeight / 2;
            int midY = GraphicsDeviceManager.DefaultBackBufferWidth / 2;
            Mouse.SetPosition(midX, midY);

            modelDrawer = new InstancedModelDrawer(this);
            modelDrawer.IsWireframe = true;

            bepuboundingboxdrawer = new BoundingBoxDrawer(this);
            bepuDrawer = new BasicEffect(GraphicsDevice);

            children.Add(camera);
            ground = new Ground();
            children.Add(ground);

            base.Initialize();
        }