忍者ブログ

Memeplexes

プログラミング、3DCGとその他いろいろについて

XNAで物理シミュレーション(JigLibX) その3

「その1」ではJigLibXのシステムを初期化しました。
「その2」では箱を描画しました。
今回、「その3」では、箱を動かします。

箱を動かすのはちょっとやっかいです。
あらたなクラスBoxActorを作ります。


プログラム

BasicWorldGame.cs
using Microsoft.Xna.Framework;
using JigLibX.Physics;
using JigLibX.Collision;

public class BasicWorldGame : Microsoft.Xna.Framework.Game
{
    GraphicsDeviceManager graphics;

    PhysicsSystem world;
    BoxActor fallingBox;
    BoxActor immovableBox;

    BoxRenderer boxRenderer;

    public BasicWorldGame()
    {
        graphics = new GraphicsDeviceManager(this);
        InitializePhysics();
    }

    private void InitializePhysics()
    {
        world = new PhysicsSystem { };
        world.CollisionSystem = new CollisionSystemSAP();

        fallingBox = new BoxActor(new Vector3(0, 20, 0), new Vector3(1, 1, 1));
        immovableBox = new BoxActor(new Vector3(0, -5, 0), new Vector3(5, 5, 5));
        immovableBox.Body.Immovable = true;

        world.AddBody(fallingBox.Body);
        world.AddBody(immovableBox.Body);
    }


    protected override void LoadContent()
    {
        boxRenderer = new BoxRenderer(GraphicsDevice);
    }

    protected override void UnloadContent()
    {
        boxRenderer.Dispose();
    }

    protected override void Update(GameTime gameTime)
    {
        world.Integrate(1f / 60);
        base.Update(gameTime);
    }

    protected override void Draw(GameTime gameTime)
    {
        GraphicsDevice.Clear(Color.CornflowerBlue);

        boxRenderer.SetCamera(
            Matrix.CreateLookAt(
                new Vector3(5, 5, 40),
                new Vector3(),
                Vector3.Up
                ),
            Matrix.CreatePerspectiveFieldOfView(
                MathHelper.ToRadians(45),
                GraphicsDevice.Viewport.AspectRatio,
                0.1f,
                1000f
                )
            );
        drawBox(fallingBox);
        drawBox(immovableBox);

        base.Draw(gameTime);
    }

    private void drawBox(BoxActor box)
    {
        boxRenderer.Draw(box.GetWorldTransform());
    }
}
BoxActor.cs
using Microsoft.Xna.Framework;
using JigLibX.Physics;
using JigLibX.Collision;
using JigLibX.Geometry;
using JigLibX.Math;

public class BoxActor 
{
    private Vector3 scale;

    public Body Body { get; private set; }
    private CollisionSkin skin;

    public BoxActor(Vector3 position, Vector3 scale)
    {
        this.scale = scale;

        this.Body = new Body();
        this.skin = new CollisionSkin(this.Body);

        this.Body.CollisionSkin = this.skin;

        this.skin.AddPrimitive(
            new Box(Vector3.Zero, Matrix.Identity, scale),
            new MaterialProperties(
                0.8f, // elasticity
                0.8f, // static roughness
                0.7f  // dynamic roughness
            ));

        SetMass(1.0f);
        this.Body.MoveTo(position, Matrix.Identity);
    }

    private void SetMass(float mass)
    {
        PrimitiveProperties primitiveProperties = new PrimitiveProperties(
            PrimitiveProperties.MassDistributionEnum.Solid,
            PrimitiveProperties.MassTypeEnum.Mass,
            mass
            );

        float junk;
        Vector3 centerOfMass;
        Matrix inertiaTensor, inertiaTensorCenterOfMass;

        this.skin.GetMassProperties(
            primitiveProperties,
            out junk, 
            out centerOfMass,
            out inertiaTensor,
            out inertiaTensorCenterOfMass
            );

        this.Body.BodyInertia = inertiaTensorCenterOfMass;
        this.Body.Mass = mass;
        this.skin.ApplyLocalTransform(new Transform(-centerOfMass, Matrix.Identity));
    }

    public Matrix GetWorldTransform()
    {
        return Matrix.CreateScale(scale)
            * skin.GetPrimitiveLocal(0).Transform.Orientation
            * Body.Orientation
            * Matrix.CreateTranslation(Body.Position);
    }
}


JigLibXDemo03.jpg


このシミュレーションには大きな箱と小さな箱が登場します。
大きな箱は空中に固定されていて、どんなことをしても動きません。

一方小さな箱は自由に動きます。
重力の影響を受けて下へ落下します。
落下していき最後は大きな箱に衝突しバウンスするのです。








拍手[0回]

PR