• libgdx 3D Bullet 碰撞检测三


    原文地址:http://blog.xoppa.com/using-the-libgdx-3d-physics-bullet-wrapper-part2/

    推荐看原文,我就直接上代码了。完整代码原文中有github。

      1 package org.forus.game.test;
      2 
      3 import com.badlogic.gdx.ApplicationListener;
      4 import com.badlogic.gdx.Gdx;
      5 import com.badlogic.gdx.graphics.Color;
      6 import com.badlogic.gdx.graphics.GL20;
      7 import com.badlogic.gdx.graphics.PerspectiveCamera;
      8 import com.badlogic.gdx.graphics.VertexAttributes.Usage;
      9 import com.badlogic.gdx.graphics.g3d.*;
     10 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
     11 import com.badlogic.gdx.graphics.g3d.environment.DirectionalLight;
     12 import com.badlogic.gdx.graphics.g3d.utils.CameraInputController;
     13 import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder;
     14 import com.badlogic.gdx.math.MathUtils;
     15 import com.badlogic.gdx.math.Matrix4;
     16 import com.badlogic.gdx.math.Vector3;
     17 import com.badlogic.gdx.physics.bullet.Bullet;
     18 import com.badlogic.gdx.physics.bullet.collision.*;
     19 import com.badlogic.gdx.physics.bullet.dynamics.*;
     20 import com.badlogic.gdx.physics.bullet.linearmath.btMotionState;
     21 import com.badlogic.gdx.utils.Array;
     22 import com.badlogic.gdx.utils.ArrayMap;
     23 import com.badlogic.gdx.utils.Disposable;
     24 
     25 public class CollisionWorldTest2 implements ApplicationListener {
     26     final static short GROUND_FLAG = 1<<8;
     27     final static short OBJECT_FLAG = 1<<9;
     28     final static short ALL_FLAG = -1;
     29 
     30     class MyContactListener extends ContactListener {
     31         /**
     32         @Override
     33         public boolean onContactAdded (int userValue0, int partId0, int index0, int userValue1, int partId1, int index1) {
     34 //            instances.get(userValue0).moving = false;
     35 //            instances.get(userValue1).moving = false;
     36 //            if (userValue0 != 0)
     37 //                ((ColorAttribute)instances.get(userValue0).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);
     38 //            if (userValue1 != 0)
     39 //                ((ColorAttribute)instances.get(userValue1).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);
     40             if (userValue1 == 0)
     41                 ((ColorAttribute)instances.get(userValue0).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);
     42             if (userValue0 == 0)
     43                 ((ColorAttribute)instances.get(userValue1).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);
     44             return true;
     45         }*/
     46 
     47 
     48         //Note that by default the contact callback filter will be set to zero, so overriding this method without setting the contact callback flag and filter values, will cause the callback never to be triggered.
     49         @Override
     50         public boolean onContactAdded (int userValue0, int partId0, int index0, boolean match0,
     51                                        int userValue1, int partId1, int index1, boolean match1) {
     52             if (match0)
     53                 ((ColorAttribute)instances.get(userValue0).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);
     54             if (match1)
     55                 ((ColorAttribute)instances.get(userValue1).materials.get(0).get(ColorAttribute.Diffuse)).color.set(Color.WHITE);
     56             return true;
     57         }
     58     }
     59 
     60     static class MyMotionState extends btMotionState {
     61         Matrix4 transform;
     62         @Override
     63         public void getWorldTransform (Matrix4 worldTrans) {
     64             worldTrans.set(transform);//TODO 搞清楚什么时候调用
     65         }
     66         @Override
     67         public void setWorldTransform (Matrix4 worldTrans) {
     68             transform.set(worldTrans);//TODO 搞清楚什么时候调用
     69         }
     70     }
     71 
     72     static class GameObject extends ModelInstance implements Disposable {
     73         public final btRigidBody body;
     74         public final MyMotionState motionState;
     75 
     76         public GameObject(Model model, String node, btRigidBody.btRigidBodyConstructionInfo constructionInfo) {
     77             super(model, node);
     78             motionState = new MyMotionState();
     79             motionState.transform = transform;
     80             body = new btRigidBody(constructionInfo);
     81             body.setMotionState(motionState);
     82         }
     83 
     84         @Override
     85         public void dispose() {
     86             body.dispose();
     87             motionState.dispose();
     88         }
     89 
     90         static class Constructor implements Disposable {
     91             public final Model model;
     92             public final String node;
     93             public final btCollisionShape shape;
     94             public final btRigidBody.btRigidBodyConstructionInfo constructionInfo;
     95             private static Vector3 localInertia = new Vector3();
     96 
     97             public Constructor(Model model, String node, btCollisionShape shape, float mass) {//mass--the weight of the object, 单位千克, 其他单位:米,秒
     98                 this.model = model;
     99                 this.node = node;
    100                 this.shape = shape;
    101                 //If the mass is equal or less than zero, we simply set the local inertia also to zero. Otherwise we need to calculate the local intertia
    102                 if (mass > 0f)
    103                     shape.calculateLocalInertia(mass, localInertia);
    104                 else
    105                     localInertia.set(0, 0, 0);
    106                 this.constructionInfo = new btRigidBody.btRigidBodyConstructionInfo(mass, null, shape, localInertia);
    107             }
    108 
    109             public GameObject construct() {
    110                 return new GameObject(model, node, constructionInfo);
    111             }
    112 
    113             @Override
    114             public void dispose() {
    115                 shape.dispose();
    116                 constructionInfo.dispose();
    117             }
    118         }
    119     }
    120 
    121     PerspectiveCamera cam;
    122     CameraInputController camController;
    123     ModelBatch modelBatch;
    124     Environment environment;
    125     Model model;
    126     Array<GameObject> instances;
    127     ArrayMap<String, GameObject.Constructor> constructors;
    128     float spawnTimer;
    129 
    130     btCollisionConfiguration collisionConfig;
    131     btDispatcher dispatcher;
    132     MyContactListener contactListener;
    133     btBroadphaseInterface broadphase;
    134 
    135     btDynamicsWorld dynamicsWorld;
    136     btConstraintSolver constraintSolver;
    137 
    138     float angle, speed = 90f;//ground的参数
    139 
    140     @Override
    141     public void create () {
    142         Bullet.init();
    143 
    144         modelBatch = new ModelBatch();
    145         environment = new Environment();
    146         environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
    147         environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -1f, -0.8f, -0.2f));
    148 
    149         cam = new PerspectiveCamera(67, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
    150         cam.position.set(3f, 7f, 10f);
    151         cam.lookAt(0, 4f, 0);
    152         cam.near = 1f;
    153         cam.far = 300f;
    154         cam.update();
    155 
    156         camController = new CameraInputController(cam);
    157         Gdx.input.setInputProcessor(camController);
    158 
    159         ModelBuilder mb = new ModelBuilder();
    160         mb.begin();
    161         mb.node().id = "ground";
    162         mb.part("ground", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.RED)))
    163                 .box(5f, 1f, 5f);
    164         mb.node().id = "sphere";
    165         mb.part("sphere", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.GREEN)))
    166                 .sphere(1f, 1f, 1f, 10, 10);
    167         mb.node().id = "box";
    168         mb.part("box", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.BLUE)))
    169                 .box(1f, 1f, 1f);
    170         mb.node().id = "cone";
    171         mb.part("cone", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.YELLOW)))
    172                 .cone(1f, 2f, 1f, 10);
    173         mb.node().id = "capsule";
    174         mb.part("capsule", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal, new Material(ColorAttribute.createDiffuse(Color.CYAN)))
    175                 .capsule(0.5f, 2f, 10);
    176         mb.node().id = "cylinder";
    177         mb.part("cylinder", GL20.GL_TRIANGLES, Usage.Position | Usage.Normal,
    178                 new Material(ColorAttribute.createDiffuse(Color.MAGENTA))).cylinder(1f, 2f, 1f, 10);
    179         model = mb.end();
    180 
    181         constructors = new ArrayMap<String, GameObject.Constructor>(String.class, GameObject.Constructor.class);
    182         constructors.put("ground", new GameObject.Constructor(model, "ground", new btBoxShape(new Vector3(2.5f, 0.5f, 2.5f)), 0f));
    183         constructors.put("sphere", new GameObject.Constructor(model, "sphere", new btSphereShape(0.5f), 1f));
    184         constructors.put("box", new GameObject.Constructor(model, "box", new btBoxShape(new Vector3(0.5f, 0.5f, 0.5f)), 1f));
    185         constructors.put("cone", new GameObject.Constructor(model, "cone", new btConeShape(0.5f, 2f), 1f));
    186         constructors.put("capsule", new GameObject.Constructor(model, "capsule", new btCapsuleShape(.5f, 1f), 1f));
    187         constructors.put("cylinder", new GameObject.Constructor(model, "cylinder", new btCylinderShape(new Vector3(.5f, 1f, .5f)), 1f));
    188 
    189         collisionConfig = new btDefaultCollisionConfiguration();
    190         dispatcher = new btCollisionDispatcher(collisionConfig);
    191         broadphase = new btDbvtBroadphase();
    192         constraintSolver = new btSequentialImpulseConstraintSolver();
    193         dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, constraintSolver, collisionConfig);//Discrete离散
    194         dynamicsWorld.setGravity(new Vector3(0, -10f, 0));
    195         contactListener = new MyContactListener();
    196 
    197         instances = new Array<GameObject>();
    198         GameObject object = constructors.get("ground").construct();
    199         object.body.setCollisionFlags(object.body.getCollisionFlags()
    200                 | btCollisionObject.CollisionFlags.CF_KINEMATIC_OBJECT);
    201         instances.add(object);
    202         //dynamicsWorld.addRigidBody(object.body, GROUND_FLAG, ALL_FLAG);
    203         dynamicsWorld.addRigidBody(object.body);
    204         object.body.setContactCallbackFlag(GROUND_FLAG);
    205         object.body.setContactCallbackFilter(0);//他和谁撞都不回调。放心,被撞的会回调的。
    206         object.body.setActivationState(Collision.DISABLE_DEACTIVATION);
    207     }
    208 
    209     public void spawn () {
    210         GameObject obj = constructors.values[1 + MathUtils.random(constructors.size - 2)].construct();
    211         obj.transform.setFromEulerAngles(MathUtils.random(360f), MathUtils.random(360f), MathUtils.random(360f));
    212         obj.transform.trn(MathUtils.random(-2.5f, 2.5f), 9f, MathUtils.random(-2.5f, 2.5f));
    213         //obj.body.setWorldTransform(obj.transform);
    214         obj.body.proceedToTransform(obj.transform);//有了motionState后
    215         obj.body.setUserValue(instances.size);
    216         obj.body.setCollisionFlags(obj.body.getCollisionFlags() | btCollisionObject.CollisionFlags.CF_CUSTOM_MATERIAL_CALLBACK);
    217         instances.add(obj);
    218         //dynamicsWorld.addRigidBody(obj.body, OBJECT_FLAG, GROUND_FLAG);//曾用过addCollisionObject, makes sure that for example gravity is correctly applied to each object
    219         dynamicsWorld.addRigidBody(obj.body);
    220         obj.body.setContactCallbackFlag(OBJECT_FLAG);
    221         //碰撞回调过滤要区别于碰撞过滤!!!前者在于,撞完之后调不调用,后者是能不能有碰撞计算
    222         obj.body.setContactCallbackFilter(GROUND_FLAG);//和Ground撞时回调
    223     }
    224 
    225     @Override
    226     public void render () {
    227         final float delta = Math.min(1f / 30f, Gdx.graphics.getDeltaTime());
    228 
    229         angle = (angle + delta * speed) % 360f;
    230         instances.get(0).transform.setTranslation(0, MathUtils.sinDeg(angle) * 2.5f, 0f);
    231         //instances.get(0).body.setWorldTransform(instances.get(0).transform);//有motionstate了这里多余
    232         //instances.get(0).body.activate();//设置了object.body.setActivationState(Collision.DISABLE_DEACTIVATION);
    233 
    234 
    235         // The discrete dynamics world uses a fixed time step.
    236         // This basically means that it will always use the same delta value to perform calculations.
    237         // This fixed delta value is supplied as the third argument of stepSimulation.
    238         // If the actual delta value (the first argument) is greater than the desired fixed delta value, then the calculation will be done multiple times.
    239         // The maximum number of times that this will be done (the maximum number of sub-steps) is specified by the second argument.
    240         dynamicsWorld.stepSimulation(delta, 5, 1f/60f);
    241         /*有motionState了,注释掉
    242         for (GameObject obj : instances)
    243             obj.body.getWorldTransform(obj.transform);//看起来像把body的设置给obj
    244 
    245         dynamicsWorld.performDiscreteCollisionDetection();
    246         */
    247 
    248         if ((spawnTimer -= delta) < 0) {
    249             spawn();
    250             spawnTimer = 1.5f;
    251         }
    252 
    253         camController.update();
    254 
    255         Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1.f);
    256         Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
    257 
    258         modelBatch.begin(cam);
    259         modelBatch.render(instances, environment);
    260         modelBatch.end();
    261     }
    262 
    263     @Override
    264     public void dispose () {
    265         for (GameObject obj : instances)
    266             obj.dispose();
    267         instances.clear();
    268 
    269         for (GameObject.Constructor ctor : constructors.values())
    270             ctor.dispose();
    271         constructors.clear();
    272 
    273         dynamicsWorld.dispose();
    274         constraintSolver.dispose();
    275         broadphase.dispose();
    276         dispatcher.dispose();
    277         collisionConfig.dispose();
    278 
    279         contactListener.dispose();
    280 
    281         modelBatch.dispose();
    282         model.dispose();
    283     }
    284 
    285     @Override
    286     public void pause () {
    287     }
    288 
    289     @Override
    290     public void resume () {
    291     }
    292 
    293     @Override
    294     public void resize (int width, int height) {
    295     }
    296 }
  • 相关阅读:
    Android测试入门篇
    SQL的基本知识
    正则表达式
    ES5语法
    vscode
    继承小结
    工作遇到的问题
    后台程序员的HTTP缓存
    xhr下载图片/服务器向客户端推送消息
    HTTP2.0
  • 原文地址:https://www.cnblogs.com/hanhongmin/p/3935173.html
Copyright © 2020-2023  润新知