• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.jme3.scene.plugins.blender.animations;
2 
3 import java.util.List;
4 
5 import com.jme3.animation.BoneTrack;
6 import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
7 import com.jme3.scene.plugins.blender.BlenderContext;
8 import com.jme3.scene.plugins.blender.curves.BezierCurve;
9 import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
10 import com.jme3.scene.plugins.blender.file.BlenderInputStream;
11 import com.jme3.scene.plugins.blender.file.FileBlockHeader;
12 import com.jme3.scene.plugins.blender.file.Pointer;
13 import com.jme3.scene.plugins.blender.file.Structure;
14 
15 /**
16  * This class helps to compute values from interpolation curves for features
17  * like animation or constraint influence. The curves are 3rd degree bezier
18  * curves.
19  *
20  * @author Marcin Roguski
21  */
22 public class IpoHelper extends AbstractBlenderHelper {
23 
24 	/**
25 	 * This constructor parses the given blender version and stores the result.
26 	 * Some functionalities may differ in different blender versions.
27 	 *
28 	 * @param blenderVersion
29 	 *            the version read from the blend file
30 	 * @param fixUpAxis
31 	 *            a variable that indicates if the Y asxis is the UP axis or not
32 	 */
IpoHelper(String blenderVersion, boolean fixUpAxis)33 	public IpoHelper(String blenderVersion, boolean fixUpAxis) {
34 		super(blenderVersion, fixUpAxis);
35 	}
36 
37 	/**
38 	 * This method creates an ipo object used for interpolation calculations.
39 	 *
40 	 * @param ipoStructure
41 	 *            the structure with ipo definition
42 	 * @param blenderContext
43 	 *            the blender context
44 	 * @return the ipo object
45 	 * @throws BlenderFileException
46 	 *             this exception is thrown when the blender file is somehow
47 	 *             corrupted
48 	 */
fromIpoStructure(Structure ipoStructure, BlenderContext blenderContext)49 	public Ipo fromIpoStructure(Structure ipoStructure, BlenderContext blenderContext) throws BlenderFileException {
50 		Structure curvebase = (Structure) ipoStructure.getFieldValue("curve");
51 
52 		// preparing bezier curves
53 		Ipo result = null;
54 		List<Structure> curves = curvebase.evaluateListBase(blenderContext);// IpoCurve
55 		if (curves.size() > 0) {
56 			BezierCurve[] bezierCurves = new BezierCurve[curves.size()];
57 			int frame = 0;
58 			for (Structure curve : curves) {
59 				Pointer pBezTriple = (Pointer) curve.getFieldValue("bezt");
60 				List<Structure> bezTriples = pBezTriple.fetchData(blenderContext.getInputStream());
61 				int type = ((Number) curve.getFieldValue("adrcode")).intValue();
62 				bezierCurves[frame++] = new BezierCurve(type, bezTriples, 2);
63 			}
64 			curves.clear();
65 			result = new Ipo(bezierCurves, fixUpAxis);
66 			blenderContext.addLoadedFeatures(ipoStructure.getOldMemoryAddress(), ipoStructure.getName(), ipoStructure, result);
67 		}
68 		return result;
69 	}
70 
71 	/**
72 	 * This method creates an ipo object used for interpolation calculations. It
73 	 * should be called for blender version 2.50 and higher.
74 	 *
75 	 * @param actionStructure
76 	 *            the structure with action definition
77 	 * @param blenderContext
78 	 *            the blender context
79 	 * @return the ipo object
80 	 * @throws BlenderFileException
81 	 *             this exception is thrown when the blender file is somehow
82 	 *             corrupted
83 	 */
fromAction(Structure actionStructure, BlenderContext blenderContext)84 	public Ipo fromAction(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException {
85 		Ipo result = null;
86 		List<Structure> curves = ((Structure) actionStructure.getFieldValue("curves")).evaluateListBase(blenderContext);// FCurve
87 		if (curves.size() > 0) {
88 			BezierCurve[] bezierCurves = new BezierCurve[curves.size()];
89 			int frame = 0;
90 			for (Structure curve : curves) {
91 				Pointer pBezTriple = (Pointer) curve.getFieldValue("bezt");
92 				List<Structure> bezTriples = pBezTriple.fetchData(blenderContext.getInputStream());
93 				int type = this.getCurveType(curve, blenderContext);
94 				bezierCurves[frame++] = new BezierCurve(type, bezTriples, 2);
95 			}
96 			curves.clear();
97 			result = new Ipo(bezierCurves, fixUpAxis);
98 		}
99 		return result;
100 	}
101 
102 	/**
103 	 * This method returns the type of the ipo curve.
104 	 *
105 	 * @param structure
106 	 *            the structure must contain the 'rna_path' field and
107 	 *            'array_index' field (the type is not important here)
108 	 * @param blenderContext
109 	 *            the blender context
110 	 * @return the type of the curve
111 	 */
getCurveType(Structure structure, BlenderContext blenderContext)112 	public int getCurveType(Structure structure, BlenderContext blenderContext) {
113 		// reading rna path first
114 		BlenderInputStream bis = blenderContext.getInputStream();
115 		int currentPosition = bis.getPosition();
116 		Pointer pRnaPath = (Pointer) structure.getFieldValue("rna_path");
117 		FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pRnaPath.getOldMemoryAddress());
118 		bis.setPosition(dataFileBlock.getBlockPosition());
119 		String rnaPath = bis.readString();
120 		bis.setPosition(currentPosition);
121 		int arrayIndex = ((Number) structure.getFieldValue("array_index")).intValue();
122 
123 		// determining the curve type
124 		if (rnaPath.endsWith("location")) {
125 			return Ipo.AC_LOC_X + arrayIndex;
126 		}
127 		if (rnaPath.endsWith("rotation_quaternion")) {
128 			return Ipo.AC_QUAT_W + arrayIndex;
129 		}
130 		if (rnaPath.endsWith("scale")) {
131 			return Ipo.AC_SIZE_X + arrayIndex;
132 		}
133 		if (rnaPath.endsWith("rotation")) {
134 			return Ipo.OB_ROT_X + arrayIndex;
135 		}
136 		throw new IllegalStateException("Unknown curve rna path: " + rnaPath);
137 	}
138 
139 	/**
140 	 * This method creates an ipo with only a single value. No track type is
141 	 * specified so do not use it for calculating tracks.
142 	 *
143 	 * @param constValue
144 	 *            the value of this ipo
145 	 * @return constant ipo
146 	 */
fromValue(float constValue)147 	public Ipo fromValue(float constValue) {
148 		return new ConstIpo(constValue);
149 	}
150 
151 	@Override
shouldBeLoaded(Structure structure, BlenderContext blenderContext)152 	public boolean shouldBeLoaded(Structure structure, BlenderContext blenderContext) {
153 		return true;
154 	}
155 
156 	/**
157 	 * Ipo constant curve. This is a curve with only one value and no specified
158 	 * type. This type of ipo cannot be used to calculate tracks. It should only
159 	 * be used to calculate single value for a given frame.
160 	 *
161 	 * @author Marcin Roguski
162 	 */
163 	private class ConstIpo extends Ipo {
164 
165 		/** The constant value of this ipo. */
166 		private float	constValue;
167 
168 		/**
169 		 * Constructor. Stores the constant value of this ipo.
170 		 *
171 		 * @param constValue
172 		 *            the constant value of this ipo
173 		 */
ConstIpo(float constValue)174 		public ConstIpo(float constValue) {
175 			super(null, false);
176 			this.constValue = constValue;
177 		}
178 
179 		@Override
calculateValue(int frame)180 		public float calculateValue(int frame) {
181 			return constValue;
182 		}
183 
184 		@Override
calculateValue(int frame, int curveIndex)185 		public float calculateValue(int frame, int curveIndex) {
186 			return constValue;
187 		}
188 
189 		@Override
getCurvesAmount()190 		public int getCurvesAmount() {
191 			return 0;
192 		}
193 
194 		@Override
calculateTrack(int boneIndex, int startFrame, int stopFrame, int fps, boolean boneTrack)195 		public BoneTrack calculateTrack(int boneIndex, int startFrame, int stopFrame, int fps, boolean boneTrack) {
196 			throw new IllegalStateException("Constatnt ipo object cannot be used for calculating bone tracks!");
197 		}
198 	}
199 }
200