Home | History | Annotate | Download | only in util
      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