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 }

 

转载于:https://www.cnblogs.com/hanhongmin/p/3935173.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值