1package com.jme3.scene.plugins.blender.constraints;
2
3import com.jme3.animation.Animation;
4import com.jme3.math.Transform;
5import com.jme3.math.Vector3f;
6import com.jme3.scene.Spatial;
7import com.jme3.scene.plugins.blender.BlenderContext;
8import com.jme3.scene.plugins.blender.animations.Ipo;
9import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
10import com.jme3.scene.plugins.blender.file.Structure;
11import com.jme3.scene.plugins.ogre.AnimData;
12
13/**
14 * This class represents 'Loc limit' constraint type in blender.
15 * @author Marcin Roguski (Kaelthas)
16 */
17/*package*/ class ConstraintLocLimit extends Constraint {
18    private static final int LIMIT_XMIN = 0x01;
19    private static final int LIMIT_XMAX = 0x02;
20    private static final int LIMIT_YMIN = 0x04;
21    private static final int LIMIT_YMAX = 0x08;
22    private static final int LIMIT_ZMIN = 0x10;
23    private static final int LIMIT_ZMAX = 0x20;
24
25    protected float[][] limits = new float[3][2];
26    protected int flag;
27
28	/**
29	 * This constructor creates the constraint instance.
30	 *
31	 * @param constraintStructure
32	 *            the constraint's structure (bConstraint clss in blender 2.49).
33	 * @param ownerOMA
34	 *            the old memory address of the constraint owner
35	 * @param influenceIpo
36	 *            the ipo curve of the influence factor
37	 * @param blenderContext
38	 *            the blender context
39	 * @throws BlenderFileException
40	 *             this exception is thrown when the blender file is somehow
41	 *             corrupted
42	 */
43	public ConstraintLocLimit(Structure constraintStructure, Long ownerOMA,
44			Ipo influenceIpo, BlenderContext blenderContext) throws BlenderFileException {
45		super(constraintStructure, ownerOMA, influenceIpo, blenderContext);
46
47		flag = ((Number) data.getFieldValue("flag")).intValue();
48		if(blenderContext.getBlenderKey().isFixUpAxis()) {
49			limits[0][0] = ((Number) data.getFieldValue("xmin")).floatValue();
50			limits[0][1] = ((Number) data.getFieldValue("xmax")).floatValue();
51			limits[2][0] = -((Number) data.getFieldValue("ymin")).floatValue();
52			limits[2][1] = -((Number) data.getFieldValue("ymax")).floatValue();
53			limits[1][0] = ((Number) data.getFieldValue("zmin")).floatValue();
54			limits[1][1] = ((Number) data.getFieldValue("zmax")).floatValue();
55
56			//swapping Y and X limits flag in the bitwise flag
57			int ymin = flag & LIMIT_YMIN;
58			int ymax = flag & LIMIT_YMAX;
59			int zmin = flag & LIMIT_ZMIN;
60			int zmax = flag & LIMIT_ZMAX;
61			flag &= LIMIT_XMIN | LIMIT_XMAX;//clear the other flags to swap them
62			flag |= ymin << 2;
63			flag |= ymax << 2;
64			flag |= zmin >> 2;
65			flag |= zmax >> 2;
66		} else {
67			limits[0][0] = ((Number) data.getFieldValue("xmin")).floatValue();
68			limits[0][1] = ((Number) data.getFieldValue("xmax")).floatValue();
69			limits[1][0] = ((Number) data.getFieldValue("ymin")).floatValue();
70			limits[1][1] = ((Number) data.getFieldValue("ymax")).floatValue();
71			limits[2][0] = ((Number) data.getFieldValue("zmin")).floatValue();
72			limits[2][1] = ((Number) data.getFieldValue("zmax")).floatValue();
73		}
74	}
75
76	@Override
77	protected void bakeConstraint() {
78		Object owner = this.owner.getObject();
79		AnimData animData = blenderContext.getAnimData(this.owner.getOma());
80		if(animData != null) {
81			for(Animation animation : animData.anims) {
82				BlenderTrack track = this.getTrack(owner, animData.skeleton, animation);
83				Vector3f[] translations = track.getTranslations();
84				int maxFrames = translations.length;
85				for (int frame = 0; frame < maxFrames; ++frame) {
86					this.locLimit(translations[frame], ipo.calculateValue(frame));
87				}
88				track.setKeyframes(track.getTimes(), translations, track.getRotations(), track.getScales());
89			}
90		}
91
92		if(owner instanceof Spatial) {
93			Transform ownerTransform = this.owner.getTransform();
94			Vector3f ownerLocation = ownerTransform.getTranslation();
95			this.locLimit(ownerLocation, ipo.calculateValue(0));
96			this.owner.applyTransform(ownerTransform);
97		}
98	}
99
100	/**
101	 * This method modifies the given translation.
102	 * @param translation the translation to be modified.
103	 * @param influence the influence value
104	 */
105	private void locLimit(Vector3f translation, float influence) {
106		if ((flag & LIMIT_XMIN) != 0) {
107			if (translation.x < limits[0][0]) {
108				translation.x -= (translation.x - limits[0][0]) * influence;
109			}
110		}
111		if ((flag & LIMIT_XMAX) != 0) {
112			if (translation.x > limits[0][1]) {
113				translation.x -= (translation.x - limits[0][1]) * influence;
114			}
115		}
116		if ((flag & LIMIT_YMIN) != 0) {
117			if (translation.y < limits[1][0]) {
118				translation.y -= (translation.y - limits[1][0]) * influence;
119			}
120		}
121		if ((flag & LIMIT_YMAX) != 0) {
122			if (translation.y > limits[1][1]) {
123				translation.y -= (translation.y - limits[1][1]) * influence;
124			}
125		}
126		if ((flag & LIMIT_ZMIN) != 0) {
127			if (translation.z < limits[2][0]) {
128				translation.z -= (translation.z - limits[2][0]) * influence;
129			}
130		}
131		if ((flag & LIMIT_ZMAX) != 0) {
132			if (translation.z > limits[2][1]) {
133				translation.z -= (translation.z - limits[2][1]) * influence;
134			}
135		}
136	}
137}
138