예제 #1
0
        public FluidSimulation(World world, SpriteBatch spriteBatch, SpriteFont font)
        {
            _world = world;
            _spriteBatch = spriteBatch;
            _font = font;
            _activeParticles = new List<int>(MAX_PARTICLES);
            _liquid = new FluidParticle[MAX_PARTICLES];
            _liquidDelete = new FluidParticle[MAX_PARTICLES];
            for (int i = 0; i < MAX_PARTICLES; i++)
            {
                _liquid[i] = new FluidParticle(Vector2.Zero, Vector2.Zero, false);
                _liquid[i].index = i;
            }

            _delta = new Vector2[MAX_PARTICLES];
            _scaledPositions = new Vector2[MAX_PARTICLES];
            _scaledVelocities = new Vector2[MAX_PARTICLES];

            _grid = new Dictionary<int, Dictionary<int, List<int>>>();

            _pixel = new Texture2D(_spriteBatch.GraphicsDevice, 1, 1);
            _pixel.SetData<Color>(new[] { Color.White });

            _random = new Random();

            _halfScreen = new Vector2(
                _spriteBatch.GraphicsDevice.Viewport.Width,
                _spriteBatch.GraphicsDevice.Viewport.Height) / 2f;
            _simulationAABB.LowerBound.X = -(_halfScreen.X + 100f);
            _simulationAABB.LowerBound.Y = -(_halfScreen.Y + 100f);
            _simulationAABB.UpperBound.X = _halfScreen.X + 100f;
            _simulationAABB.UpperBound.Y = _halfScreen.Y + 100f;
        }
예제 #2
0
        private void findNeighbors(FluidParticle particle)
        {
            particle.neighborCount = 0;
            Dictionary<int, List<int>> gridX;
            List<int> gridY;

            for (int nx = -1; nx < 2; nx++)
            {
                for (int ny = -1; ny < 2; ny++)
                {
                    int x = particle.ci + nx;
                    int y = particle.cj + ny;
                    if (_grid.TryGetValue(x, out gridX) && gridX.TryGetValue(y, out gridY))
                    {

                        for (int a = 0; a < gridY.Count; a++)
                        {
                            if (gridY[a] != particle.index)
                            {
                                particle.neighbors[particle.neighborCount] = gridY[a];
                                particle.neighborCount++;

                                if (particle.neighborCount >= MAX_NEIGHBORS)
                                    return;
                            }
                        }
                    }
                }
            }
        }
예제 #3
0
        public void update()
        {
            MouseState mouseState = Mouse.GetState();

            _halfScreen = new Vector2(
                _spriteBatch.GraphicsDevice.Viewport.Width,
                _spriteBatch.GraphicsDevice.Viewport.Height) / 2f;
            //_mouse = (new Vector2(mouseState.X, mouseState.Y) - _halfScreen) / Game1.scale;

            //_mouse = new Vector2(Game1.mouseTruePos.X*Game1.scale, Game1.mouseTruePos.Y*Game1.scale);
            _mouse = new Vector2(Game1.mouseTruePos.X, Game1.mouseTruePos.Y);

            if (mouseState.LeftButton == ButtonState.Pressed && !Game1.strafeMode)
                createParticle();

            // Prepare simulation
            Parallel.For(0, _numActiveParticles, i => { prepareSimulation(_activeParticles[i]); });

            // Prepare collisions
            prepareCollisions();

            // Calculate pressures
            Parallel.For(0, _numActiveParticles, i => { calculatePressure(_activeParticles[i]); });

            // Calculate forces
            Parallel.For(
                0,
                _numActiveParticles,
                () => new Vector2[MAX_PARTICLES],
                (i, state, accumulatedDelta) => calculateForce(_activeParticles[i], accumulatedDelta),
                (accumulatedDelta) =>
                {
                    lock (_calculateForcesLock)
                    {
                        for (int i = _numActiveParticles - 1; i >= 0; i--)
                        {
                            int index = _activeParticles[i];
                            _delta[index] += accumulatedDelta[index] / MULTIPLIER;
                        }
                    }
                }
            );

            // Resolve collisions
            Parallel.For(0, _numActiveParticles, i => resolveCollision(_activeParticles[i]));
            /*for (int i = 0; i < _numActiveParticles; i++)
            {
                FluidParticle particle = _liquid[_activeParticles[i]];

                //_spriteBatch.Draw(_pixel, new Vector2(2400,1800), new Rectangle(0, 0, 20, 20), Color.Black, 0f, new Vector2(1, 1), 1f, SpriteEffects.None, 0f);
                //Game1.checkGridLiquid(new Vector2(((float)particle.position.X + (particle.position.X-particle.oldPosition.X)/10)*Game1.scale, ((float)particle.position.Y + (particle.position.Y - particle.oldPosition.Y)/10))*Game1.scale);
                Game1.checkGridLiquid(new Vector2(((float)particle.position.X + (particle.position.X - particle.oldPosition.X)), ((float)particle.position.Y + (particle.position.Y - particle.oldPosition.Y))));
                //Game1.checkGridLiquid(new Vector2((float)particle.position.X, (float)particle.position.Y));
                //_spriteBatch.Draw(_pixel, (particle.position) * Game1.scale, new Rectangle(0, 0, 2, 2), Color.DarkBlue, 0f, new Vector2(1, 1), 1f, SpriteEffects.None, 0f);
            }*/

            foreach (KeyValuePair<int, Dictionary<int, List<int>>> row1 in _grid)
            {
                foreach (KeyValuePair<int, List<int>> row2 in row1.Value)
                {
                    Game1.checkGridLiquid(new Vector2((float)row1.Key * CELL_SIZE, (float)row2.Key * CELL_SIZE));
                }
            }

            bool delete;
            for (int i = 0; i < _numActiveParticles; i++)
            {
                FluidParticle particle = _liquid[_activeParticles[i]];
                delete = Game1.checkParticle(new Vector2(((float)particle.position.X + (particle.position.X - particle.oldPosition.X)), ((float)particle.position.Y + (particle.position.Y - particle.oldPosition.Y))));
                if (delete)
                {
                    particle.velocity = new Vector2(0, 0);
                    //particle.position = particle.oldPosition;
                }
                //if(particle.position.X
            }

            // Update particle cells
            for (int i = 0; i < _numActiveParticles; i++)
                moveParticle(_activeParticles[i]);

            if (clearParticles)
            {
                //_activeParticles.Clear();
                _activeParticles = new List<int>(MAX_PARTICLES);
                _liquid = new FluidParticle[MAX_PARTICLES];
                for (int i = 0; i < MAX_PARTICLES; i++)
                {
                    _liquid[i] = new FluidParticle(Vector2.Zero, Vector2.Zero, false);
                    _liquid[i].index = i;
                }

                _delta = new Vector2[MAX_PARTICLES];
                _scaledPositions = new Vector2[MAX_PARTICLES];
                _scaledVelocities = new Vector2[MAX_PARTICLES];

                _grid = new Dictionary<int, Dictionary<int, List<int>>>();
                _numActiveParticles = 0;
                clearParticles = false;
            }
        }