• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2009-2012 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 package com.jme3.scene.plugins.blender.modifiers;
33 
34 import java.util.ArrayList;
35 import java.util.Collection;
36 import java.util.List;
37 import java.util.logging.Level;
38 import java.util.logging.Logger;
39 
40 import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
41 import com.jme3.scene.plugins.blender.BlenderContext;
42 import com.jme3.scene.plugins.blender.animations.Ipo;
43 import com.jme3.scene.plugins.blender.animations.IpoHelper;
44 import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
45 import com.jme3.scene.plugins.blender.file.Pointer;
46 import com.jme3.scene.plugins.blender.file.Structure;
47 
48 /**
49  * A class that is used in modifiers calculations.
50  *
51  * @author Marcin Roguski
52  */
53 public class ModifierHelper extends AbstractBlenderHelper {
54 
55 	private static final Logger	LOGGER	= Logger.getLogger(ModifierHelper.class.getName());
56 
57 	/**
58 	 * This constructor parses the given blender version and stores the result.
59 	 * Some functionalities may differ in different blender versions.
60 	 *
61 	 * @param blenderVersion
62 	 *            the version read from the blend file
63 	 * @param fixUpAxis
64 	 *            a variable that indicates if the Y asxis is the UP axis or not
65 	 */
ModifierHelper(String blenderVersion, boolean fixUpAxis)66 	public ModifierHelper(String blenderVersion, boolean fixUpAxis) {
67 		super(blenderVersion, fixUpAxis);
68 	}
69 
70 	/**
71 	 * This method reads the given object's modifiers.
72 	 *
73 	 * @param objectStructure
74 	 *            the object structure
75 	 * @param blenderContext
76 	 *            the blender context
77 	 * @throws BlenderFileException
78 	 *             this exception is thrown when the blender file is somehow
79 	 *             corrupted
80 	 */
readModifiers(Structure objectStructure, BlenderContext blenderContext)81 	public Collection<Modifier> readModifiers(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
82 		Collection<Modifier> result = new ArrayList<Modifier>();
83 		Structure modifiersListBase = (Structure) objectStructure.getFieldValue("modifiers");
84 		List<Structure> modifiers = modifiersListBase.evaluateListBase(blenderContext);
85 		for (Structure modifierStructure : modifiers) {
86 			Modifier modifier = null;
87 			if (Modifier.ARRAY_MODIFIER_DATA.equals(modifierStructure.getType())) {
88 				modifier = new ArrayModifier(modifierStructure, blenderContext);
89 			} else if (Modifier.MIRROR_MODIFIER_DATA.equals(modifierStructure.getType())) {
90 				modifier = new MirrorModifier(modifierStructure, blenderContext);
91 			} else if (Modifier.ARMATURE_MODIFIER_DATA.equals(modifierStructure.getType())) {
92 				modifier = new ArmatureModifier(objectStructure, modifierStructure, blenderContext);
93 			} else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifierStructure.getType())) {
94 				modifier = new ParticlesModifier(modifierStructure, blenderContext);
95 			}
96 
97 			if (modifier != null) {
98 				result.add(modifier);
99 				blenderContext.addModifier(objectStructure.getOldMemoryAddress(), modifier);
100 			} else {
101 				LOGGER.log(Level.WARNING, "Unsupported modifier type: {0}", modifierStructure.getType());
102 			}
103 		}
104 
105 		// at the end read object's animation modifier (object animation is
106 		// either described by action or by ipo of the object)
107 		Modifier modifier;
108 		if (blenderVersion <= 249) {
109 			modifier = this.readAnimationModifier249(objectStructure, blenderContext);
110 		} else {
111 			modifier = this.readAnimationModifier250(objectStructure, blenderContext);
112 		}
113 		if (modifier != null) {
114 			result.add(modifier);
115 		}
116 		return result;
117 	}
118 
119 	@Override
shouldBeLoaded(Structure structure, BlenderContext blenderContext)120 	public boolean shouldBeLoaded(Structure structure, BlenderContext blenderContext) {
121 		return true;
122 	}
123 
124 	/**
125 	 * This method reads the object's animation modifier for blender version
126 	 * 2.49 and lower.
127 	 *
128 	 * @param objectStructure
129 	 *            the object's structure
130 	 * @param blenderContext
131 	 *            the blender context
132 	 * @return loaded modifier
133 	 * @throws BlenderFileException
134 	 *             this exception is thrown when the blender file is somehow
135 	 *             corrupted
136 	 */
readAnimationModifier249(Structure objectStructure, BlenderContext blenderContext)137 	private Modifier readAnimationModifier249(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
138 		Modifier result = null;
139 		Pointer pAction = (Pointer) objectStructure.getFieldValue("action");
140 		IpoHelper ipoHelper = blenderContext.getHelper(IpoHelper.class);
141 		if (pAction.isNotNull()) {
142 			Structure action = pAction.fetchData(blenderContext.getInputStream()).get(0);
143 			List<Structure> actionChannels = ((Structure) action.getFieldValue("chanbase")).evaluateListBase(blenderContext);
144 			if (actionChannels.size() == 1) {// object's animtion action has
145 												// only one channel
146 				Pointer pChannelIpo = (Pointer) actionChannels.get(0).getFieldValue("ipo");
147 				Structure ipoStructure = pChannelIpo.fetchData(blenderContext.getInputStream()).get(0);
148 				Ipo ipo = ipoHelper.fromIpoStructure(ipoStructure, blenderContext);
149 				result = new ObjectAnimationModifier(ipo, action.getName(), objectStructure.getOldMemoryAddress(), blenderContext);
150 				blenderContext.addModifier(objectStructure.getOldMemoryAddress(), result);
151 			} else {
152 				throw new IllegalStateException("Object's action cannot have more than one channel!");
153 			}
154 		} else {
155 			Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo");
156 			if (pIpo.isNotNull()) {
157 				Structure ipoStructure = pIpo.fetchData(blenderContext.getInputStream()).get(0);
158 				Ipo ipo = ipoHelper.fromIpoStructure(ipoStructure, blenderContext);
159 				result = new ObjectAnimationModifier(ipo, objectStructure.getName(), objectStructure.getOldMemoryAddress(), blenderContext);
160 				blenderContext.addModifier(objectStructure.getOldMemoryAddress(), result);
161 			}
162 		}
163 		return result;
164 	}
165 
166 	/**
167 	 * This method reads the object's animation modifier for blender version
168 	 * 2.50 and higher.
169 	 *
170 	 * @param objectStructure
171 	 *            the object's structure
172 	 * @param blenderContext
173 	 *            the blender context
174 	 * @return loaded modifier
175 	 * @throws BlenderFileException
176 	 *             this exception is thrown when the blender file is somehow
177 	 *             corrupted
178 	 */
readAnimationModifier250(Structure objectStructure, BlenderContext blenderContext)179 	private Modifier readAnimationModifier250(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
180 		Modifier result = null;
181 		Pointer pAnimData = (Pointer) objectStructure.getFieldValue("adt");
182 		if (pAnimData.isNotNull()) {
183 			Structure animData = pAnimData.fetchData(blenderContext.getInputStream()).get(0);
184 			Pointer pAction = (Pointer) animData.getFieldValue("action");
185 			if (pAction.isNotNull()) {
186 				Structure actionStructure = pAction.fetchData(blenderContext.getInputStream()).get(0);
187 				IpoHelper ipoHelper = blenderContext.getHelper(IpoHelper.class);
188 				Ipo ipo = ipoHelper.fromAction(actionStructure, blenderContext);
189 				result = new ObjectAnimationModifier(ipo, actionStructure.getName(), objectStructure.getOldMemoryAddress(), blenderContext);
190 				blenderContext.addModifier(objectStructure.getOldMemoryAddress(), result);
191 			}
192 		}
193 		return result;
194 	}
195 }
196