1 /******************************************************************************* 2 * Copyright 2011 See AUTHORS file. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 ******************************************************************************/ 16 17 package com.badlogic.gdx.tests.bullet; 18 19 import com.badlogic.gdx.Gdx; 20 import com.badlogic.gdx.graphics.Color; 21 import com.badlogic.gdx.graphics.GL20; 22 import com.badlogic.gdx.graphics.Mesh; 23 import com.badlogic.gdx.graphics.Texture; 24 import com.badlogic.gdx.graphics.VertexAttribute; 25 import com.badlogic.gdx.graphics.VertexAttributes.Usage; 26 import com.badlogic.gdx.graphics.g3d.Material; 27 import com.badlogic.gdx.graphics.g3d.Model; 28 import com.badlogic.gdx.graphics.g3d.ModelInstance; 29 import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute; 30 import com.badlogic.gdx.graphics.g3d.attributes.FloatAttribute; 31 import com.badlogic.gdx.graphics.g3d.attributes.IntAttribute; 32 import com.badlogic.gdx.graphics.g3d.attributes.TextureAttribute; 33 import com.badlogic.gdx.graphics.g3d.model.MeshPart; 34 import com.badlogic.gdx.graphics.g3d.utils.ModelBuilder; 35 import com.badlogic.gdx.graphics.glutils.ShaderProgram; 36 import com.badlogic.gdx.math.Matrix4; 37 import com.badlogic.gdx.math.Vector3; 38 import com.badlogic.gdx.physics.bullet.collision.btAxisSweep3; 39 import com.badlogic.gdx.physics.bullet.collision.btCollisionDispatcher; 40 import com.badlogic.gdx.physics.bullet.collision.btDefaultCollisionConfiguration; 41 import com.badlogic.gdx.physics.bullet.dynamics.btSequentialImpulseConstraintSolver; 42 import com.badlogic.gdx.physics.bullet.softbody.btSoftBody; 43 import com.badlogic.gdx.physics.bullet.softbody.btSoftBodyHelpers; 44 import com.badlogic.gdx.physics.bullet.softbody.btSoftBodyRigidBodyCollisionConfiguration; 45 import com.badlogic.gdx.physics.bullet.softbody.btSoftBodyWorldInfo; 46 import com.badlogic.gdx.physics.bullet.softbody.btSoftRigidDynamicsWorld; 47 48 /** @author xoppa */ 49 public class SoftBodyTest extends BaseBulletTest { 50 btSoftBodyWorldInfo worldInfo; 51 btSoftBody softBody; 52 Texture texture; 53 Mesh mesh; 54 Model model; 55 ModelInstance instance; 56 Matrix4 tmpM = new Matrix4(); 57 58 @Override createWorld()59 public BulletWorld createWorld () { 60 btDefaultCollisionConfiguration collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration(); 61 btCollisionDispatcher dispatcher = new btCollisionDispatcher(collisionConfiguration); 62 btAxisSweep3 broadphase = new btAxisSweep3(tmpV1.set(-1000, -1000, -1000), tmpV2.set(1000, 1000, 1000), 1024); 63 btSequentialImpulseConstraintSolver solver = new btSequentialImpulseConstraintSolver(); 64 btSoftRigidDynamicsWorld dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher, broadphase, solver, 65 collisionConfiguration); 66 67 worldInfo = new btSoftBodyWorldInfo(); 68 worldInfo.setBroadphase(broadphase); 69 worldInfo.setDispatcher(dispatcher); 70 worldInfo.getSparsesdf().Initialize(); 71 72 return new BulletWorld(collisionConfiguration, dispatcher, broadphase, solver, dynamicsWorld); 73 } 74 75 @Override create()76 public void create () { 77 super.create(); 78 79 world.add("ground", 0f, 0f, 0f).setColor(0.25f + 0.5f * (float)Math.random(), 0.25f + 0.5f * (float)Math.random(), 80 0.25f + 0.5f * (float)Math.random(), 1f); 81 82 float x0 = -2f, y0 = 6f, z0 = -2f; 83 float x1 = 8f, y1 = 6f, z1 = 8f; 84 Vector3 patch00 = new Vector3(x0, y0, z0); 85 Vector3 patch10 = new Vector3(x1, y1, z0); 86 Vector3 patch01 = new Vector3(x0, y0, z1); 87 Vector3 patch11 = new Vector3(x1, y1, z1); 88 softBody = btSoftBodyHelpers.CreatePatch(worldInfo, patch00, patch10, patch01, patch11, 15, 15, 15, false); 89 softBody.takeOwnership(); 90 softBody.setTotalMass(100f); 91 ((btSoftRigidDynamicsWorld)(world.collisionWorld)).addSoftBody(softBody); 92 93 final int vertCount = softBody.getNodeCount(); 94 final int faceCount = softBody.getFaceCount(); 95 mesh = new Mesh(false, vertCount, faceCount * 3, new VertexAttribute(Usage.Position, 3, ShaderProgram.POSITION_ATTRIBUTE), 96 new VertexAttribute(Usage.Normal, 3, ShaderProgram.NORMAL_ATTRIBUTE), new VertexAttribute(Usage.TextureCoordinates, 2, 97 ShaderProgram.TEXCOORD_ATTRIBUTE + "0")); 98 final int vertSize = mesh.getVertexSize() / 4; 99 mesh.getVerticesBuffer().position(0); 100 mesh.getVerticesBuffer().limit(vertCount * vertSize); 101 mesh.getIndicesBuffer().position(0); 102 mesh.getIndicesBuffer().limit(faceCount * 3); 103 softBody.getVertices(mesh.getVerticesBuffer(), vertCount, mesh.getVertexSize(), 0); 104 softBody.getIndices(mesh.getIndicesBuffer(), faceCount); 105 106 final float[] verts = new float[vertCount * vertSize]; 107 final int uvOffset = mesh.getVertexAttribute(Usage.TextureCoordinates).offset / 4; 108 final int normalOffset = mesh.getVertexAttribute(Usage.Normal).offset / 4; 109 mesh.getVertices(verts); 110 for (int i = 0; i < vertCount; i++) { 111 verts[i * vertSize + normalOffset] = 0f; 112 verts[i * vertSize + normalOffset + 1] = 1f; 113 verts[i * vertSize + normalOffset + 2] = 0f; 114 verts[i * vertSize + uvOffset] = (verts[i * vertSize] - x0) / (x1 - x0); 115 verts[i * vertSize + uvOffset + 1] = (verts[i * vertSize + 2] - z0) / (z1 - z0); 116 } 117 mesh.setVertices(verts); 118 texture = new Texture(Gdx.files.internal("data/badlogic.jpg")); 119 120 ModelBuilder builder = new ModelBuilder(); 121 builder.begin(); 122 builder.part( 123 new MeshPart("", mesh, 0, mesh.getNumIndices(), GL20.GL_TRIANGLES), 124 new Material(TextureAttribute.createDiffuse(texture), ColorAttribute.createSpecular(Color.WHITE), FloatAttribute 125 .createShininess(64f), IntAttribute.createCullFace(0))); 126 model = builder.end(); 127 128 instance = new ModelInstance(model); 129 world.add(new BulletEntity(instance, null)); 130 } 131 132 @Override dispose()133 public void dispose () { 134 ((btSoftRigidDynamicsWorld)(world.collisionWorld)).removeSoftBody(softBody); 135 softBody.dispose(); 136 softBody = null; 137 138 super.dispose(); 139 140 worldInfo.dispose(); 141 worldInfo = null; 142 instance = null; 143 model.dispose(); 144 model = null; 145 mesh = null; 146 texture.dispose(); 147 texture = null; 148 } 149 150 @Override renderWorld()151 protected void renderWorld () { 152 softBody.getVertices(mesh.getVerticesBuffer(), softBody.getNodeCount(), mesh.getVertexSize(), 0); 153 softBody.getWorldTransform(instance.transform); 154 super.renderWorld(); 155 156 // modelBatch.begin(camera); 157 // world.render(modelBatch, lights); 158 // modelBatch.render(instance, lights); 159 // modelBatch.end(); 160 } 161 162 @Override tap(float x, float y, int count, int button)163 public boolean tap (float x, float y, int count, int button) { 164 shoot(x, y, 20f); 165 return true; 166 } 167 } 168