|
|
|
@ -40,6 +40,7 @@ import java.util.List; |
|
|
|
|
import java.util.Map; |
|
|
|
|
import java.util.Map.Entry; |
|
|
|
|
import java.util.Set; |
|
|
|
|
import java.util.logging.Level; |
|
|
|
|
import java.util.logging.Logger; |
|
|
|
|
|
|
|
|
|
import com.jme3.animation.AnimControl; |
|
|
|
@ -118,7 +119,7 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
} else if (Modifier.MIRROR_MODIFIER_DATA.equals(modifier.getType())) { |
|
|
|
|
return this.applyMirrorModifierData(node, modifier, dataRepository); |
|
|
|
|
} else { |
|
|
|
|
LOGGER.warning("Modifier: " + modifier.getType() + " not yet implemented!!!"); |
|
|
|
|
LOGGER.log(Level.WARNING, "Modifier: {0} not yet implemented!!!", modifier.getType()); |
|
|
|
|
return node; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -156,21 +157,21 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
case 2:// FITCURVE
|
|
|
|
|
Pointer pCurveOb = (Pointer) modifier.getFieldValue("curve_ob"); |
|
|
|
|
float length = 0; |
|
|
|
|
if(pCurveOb.isNotNull()) { |
|
|
|
|
if (pCurveOb.isNotNull()) { |
|
|
|
|
Structure curveStructure = pCurveOb.fetchData(dataRepository.getInputStream()).get(0); |
|
|
|
|
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); |
|
|
|
|
Node curveObject = (Node)objectHelper.toObject(curveStructure, dataRepository); |
|
|
|
|
Node curveObject = (Node) objectHelper.toObject(curveStructure, dataRepository); |
|
|
|
|
Set<Number> referencesToCurveLengths = new HashSet<Number>(curveObject.getChildren().size()); |
|
|
|
|
for(Spatial spatial : curveObject.getChildren()) { |
|
|
|
|
if(spatial instanceof Geometry) { |
|
|
|
|
for (Spatial spatial : curveObject.getChildren()) { |
|
|
|
|
if (spatial instanceof Geometry) { |
|
|
|
|
Mesh mesh = ((Geometry) spatial).getMesh(); |
|
|
|
|
if(mesh instanceof Curve) { |
|
|
|
|
if (mesh instanceof Curve) { |
|
|
|
|
length += ((Curve) mesh).getLength(); |
|
|
|
|
} else { |
|
|
|
|
//if bevel object has several parts then each mesh will have the same reference
|
|
|
|
|
//to length value (and we should use only one)
|
|
|
|
|
Number curveLength = spatial.getUserData("curveLength"); |
|
|
|
|
if(curveLength!=null && !referencesToCurveLengths.contains(curveLength)) { |
|
|
|
|
if (curveLength != null && !referencesToCurveLengths.contains(curveLength)) { |
|
|
|
|
length += curveLength.floatValue(); |
|
|
|
|
referencesToCurveLengths.add(curveLength); |
|
|
|
|
} |
|
|
|
@ -189,12 +190,12 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
int offsettype = ((Number) modifier.getFieldValue("offset_type")).intValue(); |
|
|
|
|
if ((offsettype & 0x01) != 0) {// Constant offset
|
|
|
|
|
DynamicArray<Number> offsetArray = (DynamicArray<Number>) modifier.getFieldValue("offset"); |
|
|
|
|
float[] offset = new float[] { offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue() }; |
|
|
|
|
float[] offset = new float[]{offsetArray.get(0).floatValue(), offsetArray.get(1).floatValue(), offsetArray.get(2).floatValue()}; |
|
|
|
|
params.put("offset", offset); |
|
|
|
|
} |
|
|
|
|
if ((offsettype & 0x02) != 0) {// Relative offset
|
|
|
|
|
DynamicArray<Number> scaleArray = (DynamicArray<Number>) modifier.getFieldValue("scale"); |
|
|
|
|
float[] scale = new float[] { scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue() }; |
|
|
|
|
float[] scale = new float[]{scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()}; |
|
|
|
|
params.put("scale", scale); |
|
|
|
|
} |
|
|
|
|
if ((offsettype & 0x04) != 0) {// Object offset
|
|
|
|
@ -266,7 +267,7 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
loadedModifier = new AnimData(new Skeleton(bones), animations); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
LOGGER.warning("Unsupported modifier type: " + modifier.getType()); |
|
|
|
|
LOGGER.log(Level.WARNING, "Unsupported modifier type: {0}", modifier.getType()); |
|
|
|
|
} |
|
|
|
|
} else if (Modifier.PARTICLE_MODIFIER_DATA.equals(modifier.getType())) {// ****************PARTICLES MODIFIER
|
|
|
|
|
Pointer pParticleSystem = (Pointer) modifier.getFieldValue("psys"); |
|
|
|
@ -285,7 +286,7 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
|
|
|
|
|
//at the end read object's animation modifier
|
|
|
|
|
Modifier objectAnimationModifier = this.readObjectAnimation(objectStructure, dataRepository); |
|
|
|
|
if(objectAnimationModifier != null) { |
|
|
|
|
if (objectAnimationModifier != null) { |
|
|
|
|
dataRepository.addModifier(objectStructure.getOldMemoryAddress(), |
|
|
|
|
objectAnimationModifier.getType(), |
|
|
|
|
objectAnimationModifier.getJmeModifierRepresentation(), |
|
|
|
@ -306,17 +307,17 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
* this exception is thrown when the blender file is somehow corrupted |
|
|
|
|
*/ |
|
|
|
|
protected Modifier readObjectAnimation(Structure objectStructure, DataRepository dataRepository) throws BlenderFileException { |
|
|
|
|
Pointer pIpo = (Pointer)objectStructure.getFieldValue("ipo"); |
|
|
|
|
if(pIpo.isNotNull()) { |
|
|
|
|
Pointer pIpo = (Pointer) objectStructure.getFieldValue("ipo"); |
|
|
|
|
if (pIpo.isNotNull()) { |
|
|
|
|
//check if there is an action name connected with this ipo
|
|
|
|
|
String objectAnimationName = null; |
|
|
|
|
List<FileBlockHeader> actionBlocks = dataRepository.getFileBlocks(Integer.valueOf(FileBlockHeader.BLOCK_AC00)); |
|
|
|
|
for(FileBlockHeader actionBlock : actionBlocks) { |
|
|
|
|
for (FileBlockHeader actionBlock : actionBlocks) { |
|
|
|
|
Structure action = actionBlock.getStructure(dataRepository); |
|
|
|
|
List<Structure> actionChannels = ((Structure)action.getFieldValue("chanbase")).evaluateListBase(dataRepository); |
|
|
|
|
if(actionChannels.size() == 1) {//object's animtion action has only one channel
|
|
|
|
|
Pointer pChannelIpo = (Pointer)actionChannels.get(0).getFieldValue("ipo"); |
|
|
|
|
if(pChannelIpo.equals(pIpo)) { |
|
|
|
|
List<Structure> actionChannels = ((Structure) action.getFieldValue("chanbase")).evaluateListBase(dataRepository); |
|
|
|
|
if (actionChannels.size() == 1) {//object's animtion action has only one channel
|
|
|
|
|
Pointer pChannelIpo = (Pointer) actionChannels.get(0).getFieldValue("ipo"); |
|
|
|
|
if (pChannelIpo.equals(pIpo)) { |
|
|
|
|
objectAnimationName = action.getName(); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -324,7 +325,7 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
String objectName = objectStructure.getName(); |
|
|
|
|
if(objectAnimationName == null) {//set the object's animation name to object's name
|
|
|
|
|
if (objectAnimationName == null) {//set the object's animation name to object's name
|
|
|
|
|
objectAnimationName = objectName; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -332,12 +333,12 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
Structure ipoStructure = pIpo.fetchData(dataRepository.getInputStream()).get(0); |
|
|
|
|
Ipo ipo = ipoHelper.createIpo(ipoStructure, dataRepository); |
|
|
|
|
int[] animationFrames = dataRepository.getBlenderKey().getAnimationFrames(objectName, objectAnimationName); |
|
|
|
|
if(animationFrames == null) {//if the name was created here there are no frames set for the animation
|
|
|
|
|
animationFrames = new int[] {1, ipo.getLastFrame()}; |
|
|
|
|
if (animationFrames == null) {//if the name was created here there are no frames set for the animation
|
|
|
|
|
animationFrames = new int[]{1, ipo.getLastFrame()}; |
|
|
|
|
} |
|
|
|
|
int fps = dataRepository.getBlenderKey().getFps(); |
|
|
|
|
float start = (float)animationFrames[0] / (float)fps; |
|
|
|
|
float stop = (float)animationFrames[1] / (float)fps; |
|
|
|
|
float start = (float) animationFrames[0] / (float) fps; |
|
|
|
|
float stop = (float) animationFrames[1] / (float) fps; |
|
|
|
|
|
|
|
|
|
//calculating track for the only bone in this skeleton
|
|
|
|
|
BoneTrack[] tracks = new BoneTrack[1]; |
|
|
|
@ -354,7 +355,7 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
Bone bone = new Bone(null); |
|
|
|
|
bone.setBindTransforms(t.getTranslation(), t.getRotation(), t.getScale()); |
|
|
|
|
|
|
|
|
|
return new Modifier(Modifier.OBJECT_ANIMATION_MODIFIER_DATA, new AnimData(new Skeleton(new Bone[] {bone}), animations), objectStructure.getOldMemoryAddress()); |
|
|
|
|
return new Modifier(Modifier.OBJECT_ANIMATION_MODIFIER_DATA, new AnimData(new Skeleton(new Bone[]{bone}), animations), objectStructure.getOldMemoryAddress()); |
|
|
|
|
} |
|
|
|
|
return null; |
|
|
|
|
} |
|
|
|
@ -488,7 +489,11 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
|
|
|
|
|
protected Node applyObjectAnimationModifier(Node node, Modifier modifier, DataRepository dataRepository) { |
|
|
|
|
AnimData ad = (AnimData) modifier.getJmeModifierRepresentation(); |
|
|
|
|
ad.skeleton.getBone(0).setAttachNode(node); |
|
|
|
|
|
|
|
|
|
// TODO: Why is this line here? Why is this needed?
|
|
|
|
|
// Remove if necessary.
|
|
|
|
|
//ad.skeleton.getBone(0).setAttachNode(node);
|
|
|
|
|
|
|
|
|
|
return this.applyArmatureModifierData(node, modifier, dataRepository); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -508,11 +513,11 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
int fittype = ((Number) modifierData.get("fittype")).intValue(); |
|
|
|
|
float[] offset = (float[]) modifierData.get("offset"); |
|
|
|
|
if (offset == null) {// the node will be repeated several times in the same place
|
|
|
|
|
offset = new float[] { 0.0f, 0.0f, 0.0f }; |
|
|
|
|
offset = new float[]{0.0f, 0.0f, 0.0f}; |
|
|
|
|
} |
|
|
|
|
float[] scale = (float[]) modifierData.get("scale"); |
|
|
|
|
if (scale == null) {// the node will be repeated several times in the same place
|
|
|
|
|
scale = new float[] { 0.0f, 0.0f, 0.0f }; |
|
|
|
|
scale = new float[]{0.0f, 0.0f, 0.0f}; |
|
|
|
|
} else { |
|
|
|
|
// getting bounding box
|
|
|
|
|
node.updateModelBound(); |
|
|
|
@ -532,7 +537,7 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// adding object's offset
|
|
|
|
|
float[] objectOffset = new float[] { 0.0f, 0.0f, 0.0f }; |
|
|
|
|
float[] objectOffset = new float[]{0.0f, 0.0f, 0.0f}; |
|
|
|
|
Pointer pOffsetObject = (Pointer) modifierData.get("offsetob"); |
|
|
|
|
if (pOffsetObject != null) { |
|
|
|
|
FileBlockHeader offsetObjectBlock = dataRepository.getFileBlock(pOffsetObject.getOldMemoryAddress()); |
|
|
|
@ -544,13 +549,13 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
objectOffset[1] = translation.y; |
|
|
|
|
objectOffset[2] = translation.z; |
|
|
|
|
} catch (BlenderFileException e) { |
|
|
|
|
LOGGER.warning("Problems in blender file structure! Object offset cannot be applied! The problem: " + e.getMessage()); |
|
|
|
|
LOGGER.log(Level.WARNING, "Problems in blender file structure! Object offset cannot be applied! The problem: {0}", e.getMessage()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// getting start and end caps
|
|
|
|
|
Node[] caps = new Node[] { null, null }; |
|
|
|
|
Pointer[] pCaps = new Pointer[] { (Pointer) modifierData.get("startcap"), (Pointer) modifierData.get("endcap") }; |
|
|
|
|
Node[] caps = new Node[]{null, null}; |
|
|
|
|
Pointer[] pCaps = new Pointer[]{(Pointer) modifierData.get("startcap"), (Pointer) modifierData.get("endcap")}; |
|
|
|
|
for (int i = 0; i < pCaps.length; ++i) { |
|
|
|
|
if (pCaps[i] != null) { |
|
|
|
|
caps[i] = (Node) dataRepository.getLoadedFeature(pCaps[i].getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE); |
|
|
|
@ -563,10 +568,10 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
ObjectHelper objectHelper = dataRepository.getHelper(ObjectHelper.class); |
|
|
|
|
caps[i] = (Node) objectHelper.toObject(capStructure, dataRepository); |
|
|
|
|
if (caps[i] == null) { |
|
|
|
|
LOGGER.warning("Cap object '" + capStructure.getName() + "' couldn't be loaded!"); |
|
|
|
|
LOGGER.log(Level.WARNING, "Cap object ''{0}'' couldn''t be loaded!", capStructure.getName()); |
|
|
|
|
} |
|
|
|
|
} catch (BlenderFileException e) { |
|
|
|
|
LOGGER.warning("Problems in blender file structure! Cap object cannot be applied! The problem: " + e.getMessage()); |
|
|
|
|
LOGGER.log(Level.WARNING, "Problems in blender file structure! Cap object cannot be applied! The problem: {0}", e.getMessage()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -628,12 +633,12 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
protected Node applyMirrorModifierData(Node node, Modifier modifier, DataRepository dataRepository) { |
|
|
|
|
Map<String, Object> modifierData = (Map<String, Object>) modifier.getJmeModifierRepresentation(); |
|
|
|
|
int flag = ((Number) modifierData.get("flag")).intValue(); |
|
|
|
|
float[] mirrorFactor = new float[] { |
|
|
|
|
float[] mirrorFactor = new float[]{ |
|
|
|
|
(flag & 0x08) != 0 ? -1.0f : 1.0f, |
|
|
|
|
(flag & 0x10) != 0 ? -1.0f : 1.0f, |
|
|
|
|
(flag & 0x20) != 0 ? -1.0f : 1.0f |
|
|
|
|
}; |
|
|
|
|
float[] center = new float[] { 0.0f, 0.0f, 0.0f }; |
|
|
|
|
float[] center = new float[]{0.0f, 0.0f, 0.0f}; |
|
|
|
|
Pointer pObject = (Pointer) modifierData.get("mirrorob"); |
|
|
|
|
if (pObject != null) { |
|
|
|
|
Structure objectStructure; |
|
|
|
@ -648,7 +653,7 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
center[2] = translation.z; |
|
|
|
|
} |
|
|
|
|
} catch (BlenderFileException e) { |
|
|
|
|
LOGGER.severe("Cannot load mirror's reference object. Cause: " + e.getLocalizedMessage()); |
|
|
|
|
LOGGER.log(Level.SEVERE, "Cannot load mirror''s reference object. Cause: {0}", e.getLocalizedMessage()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
float tolerance = ((Number) modifierData.get("tolerance")).floatValue(); |
|
|
|
@ -693,22 +698,22 @@ public class ModifierHelper extends AbstractBlenderHelper { |
|
|
|
|
|
|
|
|
|
//modifying clone indexes
|
|
|
|
|
int vertexIndex = (i - mirrorIndex) / 3; |
|
|
|
|
if(vertexIndex % 3 == 0) { |
|
|
|
|
if (vertexIndex % 3 == 0) { |
|
|
|
|
short index = cloneIndexes.get(vertexIndex + 2); |
|
|
|
|
cloneIndexes.put(vertexIndex + 2, cloneIndexes.get(vertexIndex + 1)); |
|
|
|
|
cloneIndexes.put(vertexIndex + 1, index); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if(mirrorU) { |
|
|
|
|
if (mirrorU) { |
|
|
|
|
FloatBuffer cloneUVs = (FloatBuffer) clone.getBuffer(Type.TexCoord).getData(); |
|
|
|
|
for(int i=0;i<cloneUVs.limit();i+=2) { |
|
|
|
|
for (int i = 0; i < cloneUVs.limit(); i += 2) { |
|
|
|
|
cloneUVs.put(i, 1.0f - cloneUVs.get(i)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if(mirrorV) { |
|
|
|
|
if (mirrorV) { |
|
|
|
|
FloatBuffer cloneUVs = (FloatBuffer) clone.getBuffer(Type.TexCoord).getData(); |
|
|
|
|
for(int i=1;i<cloneUVs.limit();i+=2) { |
|
|
|
|
for (int i = 1; i < cloneUVs.limit(); i += 2) { |
|
|
|
|
cloneUVs.put(i, 1.0f - cloneUVs.get(i)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|