159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapackage com.jme3.scene.plugins.blender.animations; 259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport java.util.List; 459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 559b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.animation.BoneTrack; 659b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.AbstractBlenderHelper; 759b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.BlenderContext; 859b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.curves.BezierCurve; 959b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.exceptions.BlenderFileException; 1059b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.BlenderInputStream; 1159b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.FileBlockHeader; 1259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.Pointer; 1359b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartaimport com.jme3.scene.plugins.blender.file.Structure; 1459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 1559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta/** 1659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This class helps to compute values from interpolation curves for features 1759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * like animation or constraint influence. The curves are 3rd degree bezier 1859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * curves. 1959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Marcin Roguski 2159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 2259b2e6871c65f58fdad78cd7229c292f6a177578Scott Bartapublic class IpoHelper extends AbstractBlenderHelper { 2359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 2459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 2559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This constructor parses the given blender version and stores the result. 2659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Some functionalities may differ in different blender versions. 2759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 2859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param blenderVersion 2959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the version read from the blend file 3059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param fixUpAxis 3159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * a variable that indicates if the Y asxis is the UP axis or not 3259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 3359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public IpoHelper(String blenderVersion, boolean fixUpAxis) { 3459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super(blenderVersion, fixUpAxis); 3559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 3659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 3759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 3859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method creates an ipo object used for interpolation calculations. 3959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 4059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param ipoStructure 4159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the structure with ipo definition 4259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param blenderContext 4359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the blender context 4459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the ipo object 4559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws BlenderFileException 4659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * this exception is thrown when the blender file is somehow 4759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * corrupted 4859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 4959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Ipo fromIpoStructure(Structure ipoStructure, BlenderContext blenderContext) throws BlenderFileException { 5059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Structure curvebase = (Structure) ipoStructure.getFieldValue("curve"); 5159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 5259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // preparing bezier curves 5359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Ipo result = null; 5459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Structure> curves = curvebase.evaluateListBase(blenderContext);// IpoCurve 5559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (curves.size() > 0) { 5659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta BezierCurve[] bezierCurves = new BezierCurve[curves.size()]; 5759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int frame = 0; 5859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Structure curve : curves) { 5959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Pointer pBezTriple = (Pointer) curve.getFieldValue("bezt"); 6059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Structure> bezTriples = pBezTriple.fetchData(blenderContext.getInputStream()); 6159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int type = ((Number) curve.getFieldValue("adrcode")).intValue(); 6259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta bezierCurves[frame++] = new BezierCurve(type, bezTriples, 2); 6359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta curves.clear(); 6559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta result = new Ipo(bezierCurves, fixUpAxis); 6659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta blenderContext.addLoadedFeatures(ipoStructure.getOldMemoryAddress(), ipoStructure.getName(), ipoStructure, result); 6759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 6859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return result; 6959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 7059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 7159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 7259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method creates an ipo object used for interpolation calculations. It 7359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * should be called for blender version 2.50 and higher. 7459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 7559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param actionStructure 7659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the structure with action definition 7759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param blenderContext 7859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the blender context 7959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the ipo object 8059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @throws BlenderFileException 8159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * this exception is thrown when the blender file is somehow 8259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * corrupted 8359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 8459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Ipo fromAction(Structure actionStructure, BlenderContext blenderContext) throws BlenderFileException { 8559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Ipo result = null; 8659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Structure> curves = ((Structure) actionStructure.getFieldValue("curves")).evaluateListBase(blenderContext);// FCurve 8759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (curves.size() > 0) { 8859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta BezierCurve[] bezierCurves = new BezierCurve[curves.size()]; 8959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int frame = 0; 9059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta for (Structure curve : curves) { 9159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Pointer pBezTriple = (Pointer) curve.getFieldValue("bezt"); 9259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta List<Structure> bezTriples = pBezTriple.fetchData(blenderContext.getInputStream()); 9359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int type = this.getCurveType(curve, blenderContext); 9459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta bezierCurves[frame++] = new BezierCurve(type, bezTriples, 2); 9559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta curves.clear(); 9759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta result = new Ipo(bezierCurves, fixUpAxis); 9859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 9959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return result; 10059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 10159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 10259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 10359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method returns the type of the ipo curve. 10459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 10559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param structure 10659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the structure must contain the 'rna_path' field and 10759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 'array_index' field (the type is not important here) 10859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param blenderContext 10959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the blender context 11059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return the type of the curve 11159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 11259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int getCurveType(Structure structure, BlenderContext blenderContext) { 11359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // reading rna path first 11459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta BlenderInputStream bis = blenderContext.getInputStream(); 11559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int currentPosition = bis.getPosition(); 11659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta Pointer pRnaPath = (Pointer) structure.getFieldValue("rna_path"); 11759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pRnaPath.getOldMemoryAddress()); 11859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta bis.setPosition(dataFileBlock.getBlockPosition()); 11959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta String rnaPath = bis.readString(); 12059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta bis.setPosition(currentPosition); 12159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta int arrayIndex = ((Number) structure.getFieldValue("array_index")).intValue(); 12259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 12359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta // determining the curve type 12459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (rnaPath.endsWith("location")) { 12559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return Ipo.AC_LOC_X + arrayIndex; 12659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 12759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (rnaPath.endsWith("rotation_quaternion")) { 12859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return Ipo.AC_QUAT_W + arrayIndex; 12959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (rnaPath.endsWith("scale")) { 13159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return Ipo.AC_SIZE_X + arrayIndex; 13259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta if (rnaPath.endsWith("rotation")) { 13459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return Ipo.OB_ROT_X + arrayIndex; 13559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Unknown curve rna path: " + rnaPath); 13759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 13859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 13959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 14059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * This method creates an ipo with only a single value. No track type is 14159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * specified so do not use it for calculating tracks. 14259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 14359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param constValue 14459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the value of this ipo 14559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @return constant ipo 14659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 14759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public Ipo fromValue(float constValue) { 14859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return new ConstIpo(constValue); 14959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 15259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public boolean shouldBeLoaded(Structure structure, BlenderContext blenderContext) { 15359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return true; 15459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 15559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 15659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 15759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Ipo constant curve. This is a curve with only one value and no specified 15859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * type. This type of ipo cannot be used to calculate tracks. It should only 15959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * be used to calculate single value for a given frame. 16059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 16159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @author Marcin Roguski 16259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 16359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private class ConstIpo extends Ipo { 16459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** The constant value of this ipo. */ 16659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta private float constValue; 16759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 16859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta /** 16959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * Constructor. Stores the constant value of this ipo. 17059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * 17159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * @param constValue 17259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta * the constant value of this ipo 17359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta */ 17459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public ConstIpo(float constValue) { 17559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta super(null, false); 17659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta this.constValue = constValue; 17759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 17859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 17959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 18059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float calculateValue(int frame) { 18159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return constValue; 18259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 18559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public float calculateValue(int frame, int curveIndex) { 18659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return constValue; 18759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 18859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 18959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 19059b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public int getCurvesAmount() { 19159b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta return 0; 19259b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19359b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta 19459b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta @Override 19559b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta public BoneTrack calculateTrack(int boneIndex, int startFrame, int stopFrame, int fps, boolean boneTrack) { 19659b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta throw new IllegalStateException("Constatnt ipo object cannot be used for calculating bone tracks!"); 19759b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19859b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta } 19959b2e6871c65f58fdad78cd7229c292f6a177578Scott Barta} 200