MobileMesh

Discuss any questions about BEPUphysics or problems encountered.
Post Reply
vectoroO
Posts: 2
Joined: Wed Aug 17, 2011 10:55 am

MobileMesh

Post by vectoroO »

Hi there, i have a little problem using Mobil Mesh.
I made a simple pinball game, with only 4 elements: table, ball, 2 bumpers;
table and ball works perfectly(both physics and drawing), but i cant setup the bumpers.

when I draw Meshes!(not models), it has no scale and wrong orientation. I can't get how draw meshes using information from MobileMeshes.
here is all of the code:

Code: Select all

 System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using BEPUphysics;
using BEPUphysics.Collidables;
using BEPUphysics.CollisionShapes;
using BEPUphysics.Constraints;
using BEPUphysics.Entities;
using BEPUphysics.Materials;
using BEPUphysics.CollisionRuleManagement;
using BEPUphysics.Entities.Prefabs;
using BEPUphysics.DataStructures;
using BEPUphysics.MathExtensions;

namespace WindowsGame5
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Game : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        Space space;
        SpriteBatch spriteBatch;
        Camera Camera;
        Model Table_model,Left_model, Right_model,Ball_model;
        Sphere Ball_ent;
        StaticMesh Table_ent;
        MobileMesh Left_ent, Right_ent;
        public MouseState MouseState;
        public KeyboardState KeyboardState;

        public Game()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
            graphics.PreferMultiSampling = true;
        }

       
        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            // TODO: Add your initialization logic here
            space = new Space(); //Create a space that will handle physics.
            space.ForceUpdater.Gravity = (new Vector3(0,-(float)Math.Sin(MathHelper.ToRadians(80)),(float)Math.Cos(MathHelper.ToRadians(80))) ) *10;// create a gravity, it is inclined to simulate table inclination, it's bit easier that rotating table;
            KeyboardState = new KeyboardState();
            MouseState = new MouseState();
            Camera = new Camera(this,new Vector3(4f, 20f, 10f), 10);
            base.Initialize();
        }



        

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);
            //Load all models that will be used in  this Alpha;
            //And enable default lght for each;
            Table_model = Content.Load<Model>("pinballtable");
            
            Left_model = Content.Load<Model>("LeftFl");
            
            Right_model = Content.Load<Model>("RightFl");
            
            Ball_model = Content.Load<Model>("ball");
            

            //Create an entity for each model that Physics will work with;
            //first of all the table;
            Vector3[] V;
            int[] I;
            TriangleMesh.GetVerticesAndIndicesFromModel(Table_model, out V, out I); //get data about shapes.
            Table_ent = new StaticMesh(V, I); //asign data to a staticmesh entity;
            space.Add(Table_ent); // Add tabl to space, now you can collide eith it;

            // ball, as moving sphere to reduce calculs;
            Ball_ent = new Sphere(Ball_model.Bones[0].Transform.Translation, Ball_model.Meshes[0].BoundingSphere.Radius, 10f); //position from bones transform, radius from actual model radius, and a random mass value;
            Ball_ent.Material.Bounciness = 0f;
            Ball_ent.Material.KineticFriction = .8f;
            space.Add(Ball_ent); // Add ball to space, now we have a ball on table!super

            //Bumpers, two boxes left and right, but i will make them MobileMesh because soon they wont be boxes bun coplex shape.
            // first  left bumper;

            TriangleMesh.GetVerticesAndIndicesFromModel(Left_model,out V,out I);
            Left_ent = new MobileMesh(V, I, AffineTransform.Identity, MobileMeshSolidity.Solid); // this is the dclaration;
            Left_ent.Position = Left_model.Bones[0].Transform.Translation; // position need to be setup manually becauseof mobileMesh particularities;
            Left_ent.OrientationMatrix = Matrix3X3.CreateFromMatrix(Left_model.Bones[0].Transform);// orientation need to be set manually too;
            space.Add(Left_ent);// Thats all for left bumper!

            //right bumper
            TriangleMesh.GetVerticesAndIndicesFromModel(Right_model,out V,out I);
            Right_ent = new MobileMesh(V, I, AffineTransform.Identity, MobileMeshSolidity.Clockwise); // this is the dclaration, I use clockwise solidity just cuz it's cheapier;
            Right_ent.Position = Right_model.Bones[0].Transform.Translation; // position need to be setup manually becauseof mobileMesh particularities;
            Right_ent.Orientation = Quaternion.CreateFromRotationMatrix(Right_model.Bones[0].Transform);// orientation need to be set manually too;
            space.Add(Right_ent);// Thats all for right bumper!


            // TODO: use this.Content to load your game content here
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            // Allows the game to exit
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed|| KeyboardState.IsKeyDown(Keys.Escape))
                this.Exit();
            MouseState = Mouse.GetState();
            KeyboardState = Keyboard.GetState();
            space.Update();
            Camera.Update((float)gameTime.ElapsedGameTime.TotalSeconds);
            // TODO: Add your update logic here

            if(KeyboardState.IsKeyDown(Keys.Up)){
                Vector3 v = new Vector3(0,0,-5);
                    Ball_ent.ApplyLinearImpulse(ref v);
            }
            if(KeyboardState.IsKeyDown(Keys.Down)){
                Vector3 v = new Vector3(0,0,5);
                    Ball_ent.ApplyLinearImpulse(ref v);
            }
            if(KeyboardState.IsKeyDown(Keys.Left)){
                Vector3 v = new Vector3(-5,0,0);
                    Ball_ent.ApplyLinearImpulse(ref v);
            }
            if(KeyboardState.IsKeyDown(Keys.Right)){
                Vector3 v = new Vector3(5,0,0);
                    Ball_ent.ApplyLinearImpulse(ref v);
            }
            
            base.Update(gameTime);
        }


       /* Matrix M3to4(Matrix3X3 M)
        {
            var M4 = new Matrix();
            M4.Forward = M.Forward;
            M4.Left = M.Left;
            M4.Up = M.Up;
            return M4;

       }
        */
        void drawFirstMesh(Model M, Entity E)// my custom method to fastly draw some models that folow their physic representation;
        {

            Matrix[] Mat = new Matrix[2];
            ModelMesh D = M.Meshes[0];
            BasicEffect B = D.Effects[0] as BasicEffect;
            B.EnableDefaultLighting();
            B.World =E.WorldTransform;
            B.Projection = Camera.ProjectionMatrix;
            B.View = Camera.ViewMatrix;
            D.Draw();
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {

           
            GraphicsDevice.Clear(Color.CornflowerBlue);
            
            Table_model.Draw(Matrix.Identity, Camera.ViewMatrix, Camera.ProjectionMatrix);
            drawFirstMesh(Ball_model, Ball_ent);
            //drawFirstMesh(Right_model, Right_ent);
            drawFirstMesh(Left_model, Left_ent);            
            // TODO: Add your drawing code here

            base.Draw(gameTime);
        }
    }
}
please help.

PS. Norbo thanks for help with registration.
Last edited by vectoroO on Wed Aug 17, 2011 5:04 pm, edited 2 times in total.
vectoroO
Posts: 2
Joined: Wed Aug 17, 2011 10:55 am

Re: MobilMesh

Post by vectoroO »

I've alredy found a solution

Code: Select all

void DrawMobileModel(Model M, MobileMesh MM)
        {
            Matrix a = M.Bones[0].Transform;//note that model contents a single mesh
            a *= Matrix.CreateFromQuaternion(MM.Orientation);
            a.Translation = MM.Position;
            BasicEffect B = M.Meshes[0].Effects[0] as BasicEffect;
            B.Projection = Camera.ProjectionMatrix;
            B.View = Camera.ViewMatrix;
            B.World = a;
            M.Meshes[0].Draw();
        }
but drawed mesh is half-height higer than MobileMesh (in seems that meshes origis is bottom, but MobileMesh has origin at center)
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: MobileMesh

Post by Norbo »

but drawed mesh is half-height higer than MobileMesh (in seems that meshes origis is bottom, but MobileMesh has origin at center)
That is exactly what is happening. The MobileMesh's Position is its center of mass, computed based on its geometry. You can figure out the offset by looking at the Position of the mobile mesh after it is constructed. The Position is the offset from the mesh origin to the center of mass.

If you were constructing a MobileMeshShape to use/re-use in multiple entities, then you could also use the MobileMeshShape constructor which outputs the center.

The EntityConstructionDemo in the BEPUphysicsDemos shows examples of how to handle entities that compute their centers of mass.

By the way, when using mobile meshes, ensure that the mesh is as simple as possible- especially if you are targeting non-PC platforms. If you don't need their concavity, you can get much better performance from using either implicit shapes like boxes and spheres, or if necessary, ConvexHulls. Simplifying the geometry used in a convex hull is still a good idea.
noob87
Posts: 2
Joined: Tue May 07, 2013 9:36 am

Re: MobileMesh

Post by noob87 »

Hi thanks for the codes, it help me a lot when i trying to create different shapes of objects inside my game, but sorry to ask, is there a way to check for collision response for objects like pinball ramp, so that the pinball is able to go inside the ramp and come out? Currently the pinball is only able to detect the outside shape only... :cry:
Post Reply