1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.jme3.bullet.util; 33 34 import com.bulletphysics.collision.shapes.IndexedMesh; 35 import com.bulletphysics.dom.HeightfieldTerrainShape; 36 import com.jme3.math.FastMath; 37 import com.jme3.scene.Mesh; 38 import com.jme3.scene.VertexBuffer.Type; 39 import com.jme3.scene.mesh.IndexBuffer; 40 import com.jme3.util.BufferUtils; 41 import java.nio.ByteBuffer; 42 import java.nio.FloatBuffer; 43 44 /** 45 * Nice convenience methods for conversion between javax.vecmath and com.jme3.math 46 * Objects, also some jme to jbullet mesh conversion. 47 * @author normenhansen 48 */ 49 public class Converter { 50 51 private Converter() { 52 } 53 54 public static com.jme3.math.Vector3f convert(javax.vecmath.Vector3f oldVec) { 55 com.jme3.math.Vector3f newVec = new com.jme3.math.Vector3f(); 56 convert(oldVec, newVec); 57 return newVec; 58 } 59 60 public static com.jme3.math.Vector3f convert(javax.vecmath.Vector3f oldVec, com.jme3.math.Vector3f newVec) { 61 newVec.x = oldVec.x; 62 newVec.y = oldVec.y; 63 newVec.z = oldVec.z; 64 return newVec; 65 } 66 67 public static javax.vecmath.Vector3f convert(com.jme3.math.Vector3f oldVec) { 68 javax.vecmath.Vector3f newVec = new javax.vecmath.Vector3f(); 69 convert(oldVec, newVec); 70 return newVec; 71 } 72 73 public static javax.vecmath.Vector3f convert(com.jme3.math.Vector3f oldVec, javax.vecmath.Vector3f newVec) { 74 newVec.x = oldVec.x; 75 newVec.y = oldVec.y; 76 newVec.z = oldVec.z; 77 return newVec; 78 } 79 80 public static javax.vecmath.Quat4f convert(com.jme3.math.Quaternion oldQuat, javax.vecmath.Quat4f newQuat) { 81 newQuat.w = oldQuat.getW(); 82 newQuat.x = oldQuat.getX(); 83 newQuat.y = oldQuat.getY(); 84 newQuat.z = oldQuat.getZ(); 85 return newQuat; 86 } 87 88 public static javax.vecmath.Quat4f convert(com.jme3.math.Quaternion oldQuat) { 89 javax.vecmath.Quat4f newQuat = new javax.vecmath.Quat4f(); 90 convert(oldQuat, newQuat); 91 return newQuat; 92 } 93 94 public static com.jme3.math.Quaternion convert(javax.vecmath.Quat4f oldQuat, com.jme3.math.Quaternion newQuat) { 95 newQuat.set(oldQuat.x, oldQuat.y, oldQuat.z, oldQuat.w); 96 return newQuat; 97 } 98 99 public static com.jme3.math.Quaternion convert(javax.vecmath.Quat4f oldQuat) { 100 com.jme3.math.Quaternion newQuat = new com.jme3.math.Quaternion(); 101 convert(oldQuat, newQuat); 102 return newQuat; 103 } 104 105 public static com.jme3.math.Quaternion convert(javax.vecmath.Matrix3f oldMatrix, com.jme3.math.Quaternion newQuaternion) { 106 // the trace is the sum of the diagonal elements; see 107 // http://mathworld.wolfram.com/MatrixTrace.html 108 float t = oldMatrix.m00 + oldMatrix.m11 + oldMatrix.m22; 109 float w, x, y, z; 110 // we protect the division by s by ensuring that s>=1 111 if (t >= 0) { // |w| >= .5 112 float s = FastMath.sqrt(t + 1); // |s|>=1 ... 113 w = 0.5f * s; 114 s = 0.5f / s; // so this division isn't bad 115 x = (oldMatrix.m21 - oldMatrix.m12) * s; 116 y = (oldMatrix.m02 - oldMatrix.m20) * s; 117 z = (oldMatrix.m10 - oldMatrix.m01) * s; 118 } else if ((oldMatrix.m00 > oldMatrix.m11) && (oldMatrix.m00 > oldMatrix.m22)) { 119 float s = FastMath.sqrt(1.0f + oldMatrix.m00 - oldMatrix.m11 - oldMatrix.m22); // |s|>=1 120 x = s * 0.5f; // |x| >= .5 121 s = 0.5f / s; 122 y = (oldMatrix.m10 + oldMatrix.m01) * s; 123 z = (oldMatrix.m02 + oldMatrix.m20) * s; 124 w = (oldMatrix.m21 - oldMatrix.m12) * s; 125 } else if (oldMatrix.m11 > oldMatrix.m22) { 126 float s = FastMath.sqrt(1.0f + oldMatrix.m11 - oldMatrix.m00 - oldMatrix.m22); // |s|>=1 127 y = s * 0.5f; // |y| >= .5 128 s = 0.5f / s; 129 x = (oldMatrix.m10 + oldMatrix.m01) * s; 130 z = (oldMatrix.m21 + oldMatrix.m12) * s; 131 w = (oldMatrix.m02 - oldMatrix.m20) * s; 132 } else { 133 float s = FastMath.sqrt(1.0f + oldMatrix.m22 - oldMatrix.m00 - oldMatrix.m11); // |s|>=1 134 z = s * 0.5f; // |z| >= .5 135 s = 0.5f / s; 136 x = (oldMatrix.m02 + oldMatrix.m20) * s; 137 y = (oldMatrix.m21 + oldMatrix.m12) * s; 138 w = (oldMatrix.m10 - oldMatrix.m01) * s; 139 } 140 return newQuaternion.set(x, y, z, w); 141 } 142 143 public static javax.vecmath.Matrix3f convert(com.jme3.math.Quaternion oldQuaternion, javax.vecmath.Matrix3f newMatrix) { 144 float norm = oldQuaternion.getW() * oldQuaternion.getW() + oldQuaternion.getX() * oldQuaternion.getX() + oldQuaternion.getY() * oldQuaternion.getY() + oldQuaternion.getZ() * oldQuaternion.getZ(); 145 float s = (norm == 1f) ? 2f : (norm > 0f) ? 2f / norm : 0; 146 147 // compute xs/ys/zs first to save 6 multiplications, since xs/ys/zs 148 // will be used 2-4 times each. 149 float xs = oldQuaternion.getX() * s; 150 float ys = oldQuaternion.getY() * s; 151 float zs = oldQuaternion.getZ() * s; 152 float xx = oldQuaternion.getX() * xs; 153 float xy = oldQuaternion.getX() * ys; 154 float xz = oldQuaternion.getX() * zs; 155 float xw = oldQuaternion.getW() * xs; 156 float yy = oldQuaternion.getY() * ys; 157 float yz = oldQuaternion.getY() * zs; 158 float yw = oldQuaternion.getW() * ys; 159 float zz = oldQuaternion.getZ() * zs; 160 float zw = oldQuaternion.getW() * zs; 161 162 // using s=2/norm (instead of 1/norm) saves 9 multiplications by 2 here 163 newMatrix.m00 = 1 - (yy + zz); 164 newMatrix.m01 = (xy - zw); 165 newMatrix.m02 = (xz + yw); 166 newMatrix.m10 = (xy + zw); 167 newMatrix.m11 = 1 - (xx + zz); 168 newMatrix.m12 = (yz - xw); 169 newMatrix.m20 = (xz - yw); 170 newMatrix.m21 = (yz + xw); 171 newMatrix.m22 = 1 - (xx + yy); 172 173 return newMatrix; 174 } 175 176 public static com.jme3.math.Matrix3f convert(javax.vecmath.Matrix3f oldMatrix) { 177 com.jme3.math.Matrix3f newMatrix = new com.jme3.math.Matrix3f(); 178 convert(oldMatrix, newMatrix); 179 return newMatrix; 180 } 181 182 public static com.jme3.math.Matrix3f convert(javax.vecmath.Matrix3f oldMatrix, com.jme3.math.Matrix3f newMatrix) { 183 newMatrix.set(0, 0, oldMatrix.m00); 184 newMatrix.set(0, 1, oldMatrix.m01); 185 newMatrix.set(0, 2, oldMatrix.m02); 186 newMatrix.set(1, 0, oldMatrix.m10); 187 newMatrix.set(1, 1, oldMatrix.m11); 188 newMatrix.set(1, 2, oldMatrix.m12); 189 newMatrix.set(2, 0, oldMatrix.m20); 190 newMatrix.set(2, 1, oldMatrix.m21); 191 newMatrix.set(2, 2, oldMatrix.m22); 192 return newMatrix; 193 } 194 195 public static javax.vecmath.Matrix3f convert(com.jme3.math.Matrix3f oldMatrix) { 196 javax.vecmath.Matrix3f newMatrix = new javax.vecmath.Matrix3f(); 197 convert(oldMatrix, newMatrix); 198 return newMatrix; 199 } 200 201 public static javax.vecmath.Matrix3f convert(com.jme3.math.Matrix3f oldMatrix, javax.vecmath.Matrix3f newMatrix) { 202 newMatrix.m00 = oldMatrix.get(0, 0); 203 newMatrix.m01 = oldMatrix.get(0, 1); 204 newMatrix.m02 = oldMatrix.get(0, 2); 205 newMatrix.m10 = oldMatrix.get(1, 0); 206 newMatrix.m11 = oldMatrix.get(1, 1); 207 newMatrix.m12 = oldMatrix.get(1, 2); 208 newMatrix.m20 = oldMatrix.get(2, 0); 209 newMatrix.m21 = oldMatrix.get(2, 1); 210 newMatrix.m22 = oldMatrix.get(2, 2); 211 return newMatrix; 212 } 213 214 public static com.bulletphysics.linearmath.Transform convert(com.jme3.math.Transform in, com.bulletphysics.linearmath.Transform out) { 215 convert(in.getTranslation(), out.origin); 216 convert(in.getRotation(), out.basis); 217 return out; 218 } 219 220 public static com.jme3.math.Transform convert(com.bulletphysics.linearmath.Transform in, com.jme3.math.Transform out) { 221 convert(in.origin, out.getTranslation()); 222 convert(in.basis, out.getRotation()); 223 return out; 224 } 225 226 public static IndexedMesh convert(Mesh mesh) { 227 IndexedMesh jBulletIndexedMesh = new IndexedMesh(); 228 jBulletIndexedMesh.triangleIndexBase = ByteBuffer.allocate(mesh.getTriangleCount() * 3 * 4); 229 jBulletIndexedMesh.vertexBase = ByteBuffer.allocate(mesh.getVertexCount() * 3 * 4); 230 231 IndexBuffer indices = mesh.getIndicesAsList(); 232 233 FloatBuffer vertices = mesh.getFloatBuffer(Type.Position); 234 vertices.rewind(); 235 236 int verticesLength = mesh.getVertexCount() * 3; 237 jBulletIndexedMesh.numVertices = mesh.getVertexCount(); 238 jBulletIndexedMesh.vertexStride = 12; //3 verts * 4 bytes per. 239 for (int i = 0; i < verticesLength; i++) { 240 float tempFloat = vertices.get(); 241 jBulletIndexedMesh.vertexBase.putFloat(tempFloat); 242 } 243 244 int indicesLength = mesh.getTriangleCount() * 3; 245 jBulletIndexedMesh.numTriangles = mesh.getTriangleCount(); 246 jBulletIndexedMesh.triangleIndexStride = 12; //3 index entries * 4 bytes each. 247 for (int i = 0; i < indicesLength; i++) { 248 jBulletIndexedMesh.triangleIndexBase.putInt(indices.get(i)); 249 } 250 vertices.rewind(); 251 vertices.clear(); 252 253 return jBulletIndexedMesh; 254 } 255 256 public static Mesh convert(IndexedMesh mesh) { 257 Mesh jmeMesh = new Mesh(); 258 259 jmeMesh.setBuffer(Type.Index, 3, BufferUtils.createShortBuffer(mesh.numTriangles * 3)); 260 jmeMesh.setBuffer(Type.Position, 3, BufferUtils.createFloatBuffer(mesh.numVertices * 3)); 261 262 IndexBuffer indicess = jmeMesh.getIndexBuffer(); 263 FloatBuffer vertices = jmeMesh.getFloatBuffer(Type.Position); 264 265 for (int i = 0; i < mesh.numTriangles * 3; i++) { 266 indicess.put(i, mesh.triangleIndexBase.getInt(i * 4)); 267 } 268 269 for (int i = 0; i < mesh.numVertices * 3; i++) { 270 vertices.put(i, mesh.vertexBase.getFloat(i * 4)); 271 } 272 jmeMesh.updateCounts(); 273 jmeMesh.updateBound(); 274 jmeMesh.getFloatBuffer(Type.Position).clear(); 275 276 return jmeMesh; 277 } 278 279 public static Mesh convert(HeightfieldTerrainShape heightfieldShape) { 280 return null; //TODO!! 281 } 282 } 283