GameEntities.WaterPlane.TickPhysicsInfluence C# (CSharp) Method

TickPhysicsInfluence() public method

public TickPhysicsInfluence ( bool allowSplashes ) : void
allowSplashes bool
return void
        public void TickPhysicsInfluence( bool allowSplashes )
        {
            if( volumeBody == null )
                return;

            EngineRandom random = World.Instance.Random;

            List<SubmergedCheckItem> submergedItems = listSubmergedCheckItemAllocator.Alloc();

            Vec2 halfSize = Size * .5f;
            Bounds volumeBounds = new Bounds(
                new Vec3( Position.X - halfSize.X, Position.Y - halfSize.Y, Position.Z - physicsHeight ),
                new Vec3( Position.X + halfSize.X, Position.Y + halfSize.Y, Position.Z ) );

            Body[] bodies = PhysicsWorld.Instance.VolumeCast( volumeBounds,
                (int)ContactGroup.CastOnlyDynamic );

            foreach( Body body in bodies )
            {
                if( body.Static )
                    continue;

                Mat3 bodyRotation = body.Rotation.ToMat3();

                foreach( Shape shape in body.Shapes )
                {
                    if( shape.ContactGroup == (int)ContactGroup.NoContact )
                        continue;

                    Vec3 shapePosition = body.Position + bodyRotation * shape.Position;
                    float volume = shape.Volume;

                    switch( shape.ShapeType )
                    {
                    case Shape.Type.Box:
                        {
                            BoxShape boxShape = (BoxShape)shape;

                            Quat shapeRotation = body.Rotation;
                            if( !shape.IsIdentityTransform )
                                shapeRotation *= shape.Rotation;

                            Vec3 halfD = boxShape.Dimensions * .5f;

                            float r = Math.Min( Math.Min( halfD.X, halfD.Y ), halfD.Z );

                            Vec3i stepsCount = new Vec3i( 1, 1, 1 );
                            if( halfD.X > r * .3f )
                                stepsCount.X = 2;
                            if( halfD.Y > r * .3f )
                                stepsCount.Y = 2;
                            if( halfD.Z > r * .3f )
                                stepsCount.Z = 2;

                            for( int z = 0; z < stepsCount.Z; z++ )
                            {
                                for( int y = 0; y < stepsCount.Y; y++ )
                                {
                                    for( int x = 0; x < stepsCount.X; x++ )
                                    {
                                        Vec3 localPos = Vec3.Zero;

                                        if( stepsCount.X == 2 )
                                            localPos.X = ( x == 0 ) ? ( -halfD.X + r ) : ( halfD.X - r );
                                        if( stepsCount.Y == 2 )
                                            localPos.Y = ( y == 0 ) ? ( -halfD.Y + r ) : ( halfD.Y - r );
                                        if( stepsCount.X == 2 )
                                            localPos.Z = ( z == 0 ) ? ( -halfD.Z + r ) : ( halfD.Z - r );

                                        Vec3 pos = shapePosition + shapeRotation * localPos;

                                        submergedItems.Add( GetSphereSubmergedCoef( new Sphere( pos, r ) ) );
                                    }
                                }
                            }
                        }
                        break;

                    case Shape.Type.Capsule:
                        {
                            CapsuleShape capsuleShape = (CapsuleShape)shape;
                            float r = capsuleShape.Radius;
                            float l = capsuleShape.Length;

                            Quat shapeRotation = body.Rotation;
                            if( !shape.IsIdentityTransform )
                                shapeRotation *= shape.Rotation;

                            Vec3 pos;
                            pos = shapePosition + shapeRotation * new Vec3( 0, 0, -l * .5f );
                            submergedItems.Add( GetSphereSubmergedCoef( new Sphere( pos, r ) ) );
                            pos = shapePosition + shapeRotation * new Vec3( 0, 0, l * .5f );
                            submergedItems.Add( GetSphereSubmergedCoef( new Sphere( pos, r ) ) );
                        }
                        break;

                    case Shape.Type.Sphere:
                        {
                            SphereShape sphereShape = (SphereShape)shape;
                            float r = sphereShape.Radius;
                            submergedItems.Add( GetSphereSubmergedCoef( new Sphere( shapePosition, r ) ) );
                        }
                        break;

                    case Shape.Type.Mesh:
                        {
                            MeshShape meshShape = (MeshShape)shape;
                            Bounds b;
                            if( meshShape.GetDataBounds( out b ) )
                            {
                                float r = b.GetRadius();
                                submergedItems.Add( GetSphereSubmergedCoef( new Sphere( shapePosition,
                                    r ) ) );
                            }
                        }
                        break;
                    }

                    if( submergedItems.Count == 0 )
                        continue;

                    //calculate summary submerged coefficient and force center
                    float submergedCoef;
                    Vec3 submergedCenter;
                    {
                        if( submergedItems.Count != 1 )
                        {
                            submergedCoef = 0;
                            submergedCenter = Vec3.Zero;

                            float len = 0;
                            foreach( SubmergedCheckItem item in submergedItems )
                                len += item.coef;

                            if( len != 0 )
                            {
                                float invLen = 1.0f / len;
                                foreach( SubmergedCheckItem item in submergedItems )
                                {
                                    submergedCoef += item.coef;
                                    submergedCenter += item.center * ( item.coef * invLen );
                                }
                                submergedCoef /= (float)submergedItems.Count;
                            }
                        }
                        else
                        {
                            submergedCoef = submergedItems[ 0 ].coef;
                            submergedCenter = submergedItems[ 0 ].center;
                        }
                    }

                    //create splashes
                    if( allowSplashes && submergedItems.Count != 0 )
                    {
                        const float minimalBodyVelocity = 3;
                        const float minimalTimeBetweenSplashes = .25f;

                        float length = body.LinearVelocity.LengthFast();
                        if( length > minimalBodyVelocity )
                        {
                            int index = bodiesSplashOffTime.FindIndex( delegate( SplashOffItem item )
                            {
                                return item.body == body;
                            } );

                            if( index == -1 )
                            {
                                bool created = false;
                                Vec3 splashPosition = Vec3.Zero;

                                foreach( SubmergedCheckItem item in submergedItems )
                                {
                                    if( item.coef > 0 && item.coef < 1 )
                                    {
                                        Vec3 pos = new Vec3( item.center.X, item.center.Y, Position.Z );

                                        //no create splashes too much nearly
                                        if( created && ( pos - splashPosition ).LengthFast() < .1f )
                                            continue;

                                        //create splash
                                        splashPosition = pos;
                                        CreateSplash( WaterPlaneType.SplashTypes.Body, splashPosition );
                                        created = true;
                                    }
                                }

                                if( created )
                                {
                                    SplashOffItem item;
                                    item.body = body;
                                    item.remainingTime = minimalTimeBetweenSplashes;
                                    bodiesSplashOffTime.Add( item );
                                }
                            }
                        }
                    }

                    submergedItems.Clear();

                    if( submergedCoef == 0 )
                        continue;

                    //add forces

                    float shapeDensity = GetShapeInfluenceDensity( shape );
                    if( shapeDensity == 0 )
                        continue;

                    float densityCoef = Type.PhysicsDensity / shapeDensity;
                    float mass = volume * shape.Density;

                    //buoyancy force
                    {
                        const float roughnessLinearCoef = .5f;

                        float coef = densityCoef * submergedCoef;
                        coef += random.NextFloatCenter() * roughnessLinearCoef;

                        Vec3 vector = -PhysicsWorld.Instance.Gravity * ( mass * coef );
                        body.AddForce( ForceType.GlobalAtGlobalPos, TickDelta, vector, submergedCenter );
                    }

                    //linear damping
                    {
                        float constCoef = 2;

                        float coef = submergedCoef * constCoef * densityCoef;

                        Vec3 vector = -body.LinearVelocity * mass * coef;
                        body.AddForce( ForceType.GlobalAtGlobalPos, TickDelta, vector, submergedCenter );
                    }

                    //angular damping
                    {
                        const float constCoef = .5f;
                        const float roughnessAngularCoef = .25f;

                        float coef = submergedCoef * constCoef;

                        Vec3 vector = -body.AngularVelocity * mass * coef;

                        float roughnessX = random.NextFloatCenter() * roughnessAngularCoef;
                        float roughnessY = random.NextFloatCenter() * roughnessAngularCoef;
                        float roughnessZ = random.NextFloatCenter() * roughnessAngularCoef;
                        vector += new Vec3( roughnessX, roughnessY, roughnessZ );

                        body.AddForce( ForceType.GlobalTorque, TickDelta, vector, Vec3.Zero );
                    }
                }
            }

            listSubmergedCheckItemAllocator.Free( submergedItems );
        }