Normand Briere
2019-09-17 54adfcbf93eb477bedeec45409f36cf7e102b790
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*8
 * Make a donation http://sourceforge.net/donate/index.php?group_id=98797
 * Microcrowd.com
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 * Contact Josh DeFord jdeford@microcrowd.com
 */
 
package com.microcrowd.loader.java3d.max3ds.chunks;
 
import java.util.ArrayList;
import java.util.List;
import javax.vecmath.Quat4f;
import javax.vecmath.Vector3f;
import com.microcrowd.loader.java3d.max3ds.ChunkChopper;
 
/**
 * Extracts the rotation information from the 3ds file.
 * Rotations occur about a pivot at a position within
 * a local coordinate system. The rotation information
 * is provided to the KeyFramerInfoChunk which then converts
 * it to a global coordinate system and applies animation
 * information.
 * {@see KeyFramerInfoChunk} for more information about using
 * animations from a 3ds file
 */
public class RotationChunk extends Chunk
{
    /** 
     *  String that will be used as a data object in the transform that the 
     *  RotationInterpolator will be a child of so it may be look up later.
     **/
    public static String ROTATION_TAG = "ROTATION_INTERPOLATOR";
 
    /**
     * Loads the quaternion for a rotation of a shape
     * and notifies mesh info chunk.
     *
     * @param chopper the ChunkChopper containing the state of the parser.  
     */
    public void loadData(ChunkChopper chopper)
    {
        int flags = chopper.getUnsignedShort();
        chopper.getLong();
        int numKeys = chopper.getUnsignedInt();
 
        Quat4f previousQuat = null;
 
        List quats = new ArrayList();
        for(int i =0; i < numKeys; i++)
        {
            long         frameNumber = chopper.getUnsignedInt();//Part of the track header
            int   accelerationData = chopper.getUnsignedShort();//Part of the track header
            getSplineTerms(accelerationData, chopper);//Part of the track header
 
            float            angle = chopper.getFloat();
            Vector3f        vector = chopper.getVector(); 
 
            Quat4f quat = getQuaternion(vector, angle);
            if(previousQuat != null) {
                quat.mul(previousQuat, quat);
            }
            previousQuat = quat; 
 
            quats.add(quat); 
            if(i==0)
            {
                chopper.getKeyFramer().setRotation(quat);
            }
        }
        chopper.getKeyFramer().setOrientationKeys(quats);
    }
 
    /**
     * This only reads the spline data and should be part
     * of the track header when it gets invented.
     * @param chopper an integer representing the bits that 
     * determine which of the five possible spline terms are present in the 
     * data and should be read.
     * @param chopper what to read the data from
     * The possible spline values are are 
     * <ol>
     * <li> Tension
     * <li> Continuity
     * <li> Bias
     * <li> EaseTo
     * <li> EaseFrom
     * </ol>
     */
    private void getSplineTerms(final int accelerationData, ChunkChopper chopper)
    {
        int bits = accelerationData;
        for(int i=0; i < 5; i++)
        {
            bits = bits >>> i;
            if((bits & 1) == 1)
            {
                chopper.getFloat();
            }
        }
    }
 
    /**
     * This converts a 3ds angle and axis to 
     * a quaternion rotation.  Successive
     * rotations are relative to the first so each
     * rotation must be made absolute by multiplying
     * it with its predecessor
     */
    public Quat4f getQuaternion(Vector3f axis, float angle)
    {
        float sinA  = (float)(java.lang.Math.sin(angle/2.0f));
        float cosA  = (float)(java.lang.Math.cos(angle/2.0f));
        return new Quat4f(axis.x * sinA, axis.y * sinA, axis.z * sinA, cosA);
    }
}