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
33package com.jme3.animation;
34
35import com.jme3.export.*;
36import com.jme3.scene.Mesh;
37import com.jme3.scene.VertexBuffer;
38import com.jme3.scene.VertexBuffer.Type;
39import com.jme3.util.TempVars;
40import java.io.IOException;
41import java.nio.FloatBuffer;
42
43/**
44 * A single track of pose animation associated with a certain mesh.
45 */
46@Deprecated
47public final class PoseTrack implements Track {
48
49    private int targetMeshIndex;
50    private PoseFrame[] frames;
51    private float[] times;
52
53    public static class PoseFrame implements Savable, Cloneable {
54
55        Pose[] poses;
56        float[] weights;
57
58        public PoseFrame(Pose[] poses, float[] weights) {
59            this.poses = poses;
60            this.weights = weights;
61        }
62
63        /**
64         * This method creates a clone of the current object.
65         * @return a clone of the current object
66         */
67        @Override
68        public PoseFrame clone() {
69            try {
70                PoseFrame result = (PoseFrame) super.clone();
71                result.weights = this.weights.clone();
72                if (this.poses != null) {
73                    result.poses = new Pose[this.poses.length];
74                    for (int i = 0; i < this.poses.length; ++i) {
75                        result.poses[i] = this.poses[i].clone();
76                    }
77                }
78                return result;
79            } catch (CloneNotSupportedException e) {
80                throw new AssertionError();
81            }
82        }
83
84        public void write(JmeExporter e) throws IOException {
85            OutputCapsule out = e.getCapsule(this);
86            out.write(poses, "poses", null);
87            out.write(weights, "weights", null);
88        }
89
90        public void read(JmeImporter i) throws IOException {
91            InputCapsule in = i.getCapsule(this);
92            poses = (Pose[]) in.readSavableArray("poses", null);
93            weights = in.readFloatArray("weights", null);
94        }
95    }
96
97    public PoseTrack(int targetMeshIndex, float[] times, PoseFrame[] frames){
98        this.targetMeshIndex = targetMeshIndex;
99        this.times = times;
100        this.frames = frames;
101    }
102
103    private void applyFrame(Mesh target, int frameIndex, float weight){
104        PoseFrame frame = frames[frameIndex];
105        VertexBuffer pb = target.getBuffer(Type.Position);
106        for (int i = 0; i < frame.poses.length; i++){
107            Pose pose = frame.poses[i];
108            float poseWeight = frame.weights[i] * weight;
109
110            pose.apply(poseWeight, (FloatBuffer) pb.getData());
111        }
112
113        // force to re-upload data to gpu
114        pb.updateData(pb.getData());
115    }
116
117    public void setTime(float time, float weight, AnimControl control, AnimChannel channel, TempVars vars) {
118        // TODO: When MeshControl is created, it will gather targets
119        // list automatically which is then retrieved here.
120
121        /*
122        Mesh target = targets[targetMeshIndex];
123        if (time < times[0]) {
124            applyFrame(target, 0, weight);
125        } else if (time > times[times.length - 1]) {
126            applyFrame(target, times.length - 1, weight);
127        } else {
128            int startFrame = 0;
129            for (int i = 0; i < times.length; i++) {
130                if (times[i] < time) {
131                    startFrame = i;
132                }
133            }
134
135            int endFrame = startFrame + 1;
136            float blend = (time - times[startFrame]) / (times[endFrame] - times[startFrame]);
137            applyFrame(target, startFrame, blend * weight);
138            applyFrame(target, endFrame, (1f - blend) * weight);
139        }
140        */
141    }
142
143    /**
144     * @return the length of the track
145     */
146    public float getLength() {
147        return times == null ? 0 : times[times.length - 1] - times[0];
148    }
149
150    /**
151     * This method creates a clone of the current object.
152     * @return a clone of the current object
153     */
154    @Override
155    public PoseTrack clone() {
156        try {
157            PoseTrack result = (PoseTrack) super.clone();
158            result.times = this.times.clone();
159            if (this.frames != null) {
160                result.frames = new PoseFrame[this.frames.length];
161                for (int i = 0; i < this.frames.length; ++i) {
162                    result.frames[i] = this.frames[i].clone();
163                }
164            }
165            return result;
166        } catch (CloneNotSupportedException e) {
167            throw new AssertionError();
168        }
169    }
170
171    @Override
172    public void write(JmeExporter e) throws IOException {
173        OutputCapsule out = e.getCapsule(this);
174        out.write(targetMeshIndex, "meshIndex", 0);
175        out.write(frames, "frames", null);
176        out.write(times, "times", null);
177    }
178
179    @Override
180    public void read(JmeImporter i) throws IOException {
181        InputCapsule in = i.getCapsule(this);
182        targetMeshIndex = in.readInt("meshIndex", 0);
183        frames = (PoseFrame[]) in.readSavableArray("frames", null);
184        times = in.readFloatArray("times", null);
185    }
186}
187