use of com.jme3.scene.plugins.blender.file.Pointer in project jmonkeyengine by jMonkeyEngine.
the class ObjectHelper method toObject.
/**
* This method reads the given structure and createn an object that
* represents the data.
*
* @param objectStructure
* the object's structure
* @param blenderContext
* the blender context
* @return blener's object representation or null if its type is excluded from loading
* @throws BlenderFileException
* an exception is thrown when the given data is inapropriate
*/
public Object toObject(Structure objectStructure, BlenderContext blenderContext) throws BlenderFileException {
Object loadedResult = blenderContext.getLoadedFeature(objectStructure.getOldMemoryAddress(), LoadedDataType.FEATURE);
if (loadedResult != null) {
return loadedResult;
}
LOGGER.fine("Loading blender object.");
if ("ID".equals(objectStructure.getType())) {
Node object = (Node) this.loadLibrary(objectStructure);
if (object.getParent() != null) {
LOGGER.log(Level.FINEST, "Detaching object {0}, loaded from external file, from its parent.", object);
object.getParent().detachChild(object);
}
return object;
}
int type = ((Number) objectStructure.getFieldValue("type")).intValue();
ObjectType objectType = ObjectType.valueOf(type);
LOGGER.log(Level.FINE, "Type of the object: {0}.", objectType);
int lay = ((Number) objectStructure.getFieldValue("lay")).intValue();
if ((lay & blenderContext.getBlenderKey().getLayersToLoad()) == 0) {
LOGGER.fine("The layer this object is located in is not included in loading.");
return null;
}
blenderContext.pushParent(objectStructure);
String name = objectStructure.getName();
LOGGER.log(Level.FINE, "Loading obejct: {0}", name);
int restrictflag = ((Number) objectStructure.getFieldValue("restrictflag")).intValue();
boolean visible = (restrictflag & 0x01) != 0;
Pointer pParent = (Pointer) objectStructure.getFieldValue("parent");
Object parent = blenderContext.getLoadedFeature(pParent.getOldMemoryAddress(), LoadedDataType.FEATURE);
if (parent == null && pParent.isNotNull()) {
Structure parentStructure = pParent.fetchData().get(0);
parent = this.toObject(parentStructure, blenderContext);
}
Transform t = this.getTransformation(objectStructure, blenderContext);
LOGGER.log(Level.FINE, "Importing object of type: {0}", objectType);
Node result = null;
try {
switch(objectType) {
case LATTICE:
case METABALL:
case TEXT:
case WAVE:
LOGGER.log(Level.WARNING, "{0} type is not supported but the node will be returned in order to keep parent - child relationship.", objectType);
case EMPTY:
case ARMATURE:
// need to use an empty node to properly create
// parent-children relationships between nodes
result = new Node(name);
break;
case MESH:
result = new Node(name);
MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
Pointer pMesh = (Pointer) objectStructure.getFieldValue("data");
List<Structure> meshesArray = pMesh.fetchData();
TemporalMesh temporalMesh = meshHelper.toTemporalMesh(meshesArray.get(0), blenderContext);
if (temporalMesh != null) {
result.attachChild(temporalMesh);
}
break;
case SURF:
case CURVE:
result = new Node(name);
Pointer pCurve = (Pointer) objectStructure.getFieldValue("data");
if (pCurve.isNotNull()) {
CurvesHelper curvesHelper = blenderContext.getHelper(CurvesHelper.class);
Structure curveData = pCurve.fetchData().get(0);
TemporalMesh curvesTemporalMesh = curvesHelper.toCurve(curveData, blenderContext);
if (curvesTemporalMesh != null) {
result.attachChild(curvesTemporalMesh);
}
}
break;
case LAMP:
Pointer pLamp = (Pointer) objectStructure.getFieldValue("data");
if (pLamp.isNotNull()) {
LightHelper lightHelper = blenderContext.getHelper(LightHelper.class);
List<Structure> lampsArray = pLamp.fetchData();
Light light = lightHelper.toLight(lampsArray.get(0), blenderContext);
if (light == null) {
// probably some light type is not supported, just create a node so that we can maintain child-parent relationship for nodes
result = new Node(name);
} else {
result = new LightNode(name, light);
}
}
break;
case CAMERA:
Pointer pCamera = (Pointer) objectStructure.getFieldValue("data");
if (pCamera.isNotNull()) {
CameraHelper cameraHelper = blenderContext.getHelper(CameraHelper.class);
List<Structure> camerasArray = pCamera.fetchData();
Camera camera = cameraHelper.toCamera(camerasArray.get(0), blenderContext);
if (camera == null) {
// just create a node so that we can maintain child-parent relationship for nodes
result = new Node(name);
} else {
result = new CameraNode(name, camera);
}
}
break;
default:
LOGGER.log(Level.WARNING, "Unsupported object type: {0}", type);
}
if (result != null) {
LOGGER.fine("Storing loaded feature in blender context and applying markers (those will be removed before the final result is released).");
Long oma = objectStructure.getOldMemoryAddress();
blenderContext.addLoadedFeatures(oma, LoadedDataType.STRUCTURE, objectStructure);
blenderContext.addLoadedFeatures(oma, LoadedDataType.FEATURE, result);
blenderContext.addMarker(OMA_MARKER, result, objectStructure.getOldMemoryAddress());
if (objectType == ObjectType.ARMATURE) {
blenderContext.addMarker(ARMATURE_NODE_MARKER, result, Boolean.TRUE);
}
result.setLocalTransform(t);
result.setCullHint(visible ? CullHint.Always : CullHint.Inherit);
if (parent instanceof Node) {
((Node) parent).attachChild(result);
}
LOGGER.fine("Reading and applying object's modifiers.");
ModifierHelper modifierHelper = blenderContext.getHelper(ModifierHelper.class);
Collection<Modifier> modifiers = modifierHelper.readModifiers(objectStructure, blenderContext);
for (Modifier modifier : modifiers) {
modifier.apply(result, blenderContext);
}
if (result.getChildren() != null && result.getChildren().size() > 0) {
if (result.getChildren().size() == 1 && result.getChild(0) instanceof TemporalMesh) {
LOGGER.fine("Converting temporal mesh into jme geometries.");
((TemporalMesh) result.getChild(0)).toGeometries();
}
LOGGER.fine("Applying proper scale to the geometries.");
for (Spatial child : result.getChildren()) {
if (child instanceof Geometry) {
this.flipMeshIfRequired((Geometry) child, child.getWorldScale());
}
}
}
// I prefer do compute bounding box here than read it from the file
result.updateModelBound();
LOGGER.fine("Applying animations to the object if such are defined.");
AnimationHelper animationHelper = blenderContext.getHelper(AnimationHelper.class);
animationHelper.applyAnimations(result, blenderContext.getBlenderKey().getAnimationMatchMethod());
LOGGER.fine("Loading constraints connected with this object.");
ConstraintHelper constraintHelper = blenderContext.getHelper(ConstraintHelper.class);
constraintHelper.loadConstraints(objectStructure, blenderContext);
LOGGER.fine("Loading custom properties.");
if (blenderContext.getBlenderKey().isLoadObjectProperties()) {
Properties properties = this.loadProperties(objectStructure, blenderContext);
// each value and set it to Spatial
if (properties != null && properties.getValue() != null) {
this.applyProperties(result, properties);
}
}
}
} finally {
blenderContext.popParent();
}
return result;
}
use of com.jme3.scene.plugins.blender.file.Pointer in project jmonkeyengine by jMonkeyEngine.
the class Properties method load.
/**
* This method loads the property from the belnder file.
* @param idPropertyStructure
* the ID structure constining the property
* @param blenderContext
* the blender context
* @throws BlenderFileException
* an exception is thrown when the belnder file is somehow invalid
*/
public void load(Structure idPropertyStructure, BlenderContext blenderContext) throws BlenderFileException {
name = idPropertyStructure.getFieldValue("name").toString();
if (name == null || name.length() == 0) {
name = DEFAULT_NAME;
}
subType = ((Number) idPropertyStructure.getFieldValue("subtype")).intValue();
type = ((Number) idPropertyStructure.getFieldValue("type")).intValue();
// reading the data
Structure data = (Structure) idPropertyStructure.getFieldValue("data");
int len = ((Number) idPropertyStructure.getFieldValue("len")).intValue();
switch(type) {
case IDP_STRING:
{
Pointer pointer = (Pointer) data.getFieldValue("pointer");
BlenderInputStream bis = blenderContext.getInputStream();
FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pointer.getOldMemoryAddress());
bis.setPosition(dataFileBlock.getBlockPosition());
value = bis.readString();
break;
}
case IDP_INT:
int intValue = ((Number) data.getFieldValue("val")).intValue();
value = Integer.valueOf(intValue);
break;
case IDP_FLOAT:
int floatValue = ((Number) data.getFieldValue("val")).intValue();
value = Float.valueOf(Float.intBitsToFloat(floatValue));
break;
case IDP_ARRAY:
{
Pointer pointer = (Pointer) data.getFieldValue("pointer");
BlenderInputStream bis = blenderContext.getInputStream();
FileBlockHeader dataFileBlock = blenderContext.getFileBlock(pointer.getOldMemoryAddress());
bis.setPosition(dataFileBlock.getBlockPosition());
int elementAmount = dataFileBlock.getSize();
switch(subType) {
case IDP_INT:
elementAmount /= 4;
int[] intList = new int[elementAmount];
for (int i = 0; i < elementAmount; ++i) {
intList[i] = bis.readInt();
}
value = intList;
break;
case IDP_FLOAT:
elementAmount /= 4;
float[] floatList = new float[elementAmount];
for (int i = 0; i < elementAmount; ++i) {
floatList[i] = bis.readFloat();
}
value = floatList;
break;
case IDP_DOUBLE:
elementAmount /= 8;
double[] doubleList = new double[elementAmount];
for (int i = 0; i < elementAmount; ++i) {
doubleList[i] = bis.readDouble();
}
value = doubleList;
break;
default:
throw new IllegalStateException("Invalid array subtype: " + subType);
}
}
case IDP_GROUP:
Structure group = (Structure) data.getFieldValue("group");
List<Structure> dataList = group.evaluateListBase();
List<Properties> subProperties = new ArrayList<Properties>(len);
for (Structure d : dataList) {
Properties properties = new Properties();
properties.load(d, blenderContext);
subProperties.add(properties);
}
value = subProperties;
break;
case IDP_DOUBLE:
int doublePart1 = ((Number) data.getFieldValue("val")).intValue();
int doublePart2 = ((Number) data.getFieldValue("val2")).intValue();
long doubleVal = (long) doublePart2 << 32 | doublePart1;
value = Double.valueOf(Double.longBitsToDouble(doubleVal));
break;
case IDP_IDPARRAY:
{
Pointer pointer = (Pointer) data.getFieldValue("pointer");
List<Structure> arrays = pointer.fetchData();
List<Object> result = new ArrayList<Object>(arrays.size());
Properties temp = new Properties();
for (Structure array : arrays) {
temp.load(array, blenderContext);
result.add(temp.value);
}
value = result;
break;
}
case IDP_NUMTYPES:
throw new UnsupportedOperationException();
// return null;
default:
throw new IllegalStateException("Unknown custom property type: " + type);
}
this.completeLoading();
}
use of com.jme3.scene.plugins.blender.file.Pointer in project jmonkeyengine by jMonkeyEngine.
the class CurvesTemporalMesh method loadBevelObject.
/**
* The method loads the bevel object that sould be applied to curve. It can either be another curve or a generated one
* based on the bevel generating parameters in blender.
* @param curveStructure
* the structure with the curve's data (the curve being loaded, NOT the bevel curve)
* @return the curve's bevel object
* @throws BlenderFileException
* an exception is thrown when problems with reading occur
*/
@SuppressWarnings("unchecked")
private CurvesTemporalMesh loadBevelObject(Structure curveStructure) throws BlenderFileException {
CurvesTemporalMesh bevelObject = null;
Pointer pBevelObject = (Pointer) curveStructure.getFieldValue("bevobj");
boolean cyclic = false;
if (pBevelObject.isNotNull()) {
Structure bevelObjectStructure = pBevelObject.fetchData().get(0);
DynamicArray<Number> scaleArray = (DynamicArray<Number>) bevelObjectStructure.getFieldValue("size");
Vector3f scale = blenderContext.getBlenderKey().isFixUpAxis() ? new Vector3f(scaleArray.get(0).floatValue(), scaleArray.get(1).floatValue(), scaleArray.get(2).floatValue()) : new Vector3f(scaleArray.get(0).floatValue(), scaleArray.get(2).floatValue(), scaleArray.get(1).floatValue());
Pointer pBevelStructure = (Pointer) bevelObjectStructure.getFieldValue("data");
Structure bevelStructure = pBevelStructure.fetchData().get(0);
bevelObject = new CurvesTemporalMesh(bevelStructure, scale, false, blenderContext);
// transforming the bezier lines from plane XZ to plane YZ
for (BezierLine bl : bevelObject.beziers) {
for (Vector3f v : bl.vertices) {
// casting the bezier curve orthogonally on the plane XZ (making Y = 0) and then moving the plane XZ to ZY in a way that:
// -Z => +Y and +X => +Z and +Y => +X (but because casting would make Y = 0, then we simply set X = 0)
v.y = -v.z;
v.z = v.x;
v.x = 0;
}
// bevel curves should not have repeated the first vertex at the end when they are cyclic (this is handled differently)
if (bl.isCyclic()) {
bl.removeLastVertex();
}
}
} else {
// this option is inactive in blender when there is no bevel object applied
fillCaps = false;
int bevResol = ((Number) curveStructure.getFieldValue("bevresol")).intValue();
float extrude = ((Number) curveStructure.getFieldValue("ext1")).floatValue();
float bevelDepth = ((Number) curveStructure.getFieldValue("ext2")).floatValue();
float offset = ((Number) curveStructure.getFieldValue("offset", 0)).floatValue();
if (offset != 0) {
// TODO: add support for offset parameter
LOGGER.warning("Offset parameter not yet supported.");
}
Curve bevelCurve = null;
if (bevelDepth > 0.0f) {
float handlerLength = bevelDepth / 2.0f;
cyclic = !isFront && !isBack;
List<Vector3f> conrtolPoints = new ArrayList<Vector3f>();
// when neither fron and back face is selected all version behave the same and draw full bevel around the curve
if (cyclic || blenderContext.getBlenderVersion() < 253) {
conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, 0));
conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, -handlerLength));
conrtolPoints.add(new Vector3f(0, -extrude - handlerLength, -bevelDepth));
conrtolPoints.add(new Vector3f(0, -extrude, -bevelDepth));
conrtolPoints.add(new Vector3f(0, -extrude + handlerLength, -bevelDepth));
if (extrude > 0) {
conrtolPoints.add(new Vector3f(0, extrude - handlerLength, -bevelDepth));
conrtolPoints.add(new Vector3f(0, extrude, -bevelDepth));
conrtolPoints.add(new Vector3f(0, extrude + handlerLength, -bevelDepth));
}
conrtolPoints.add(new Vector3f(0, extrude + bevelDepth, -handlerLength));
conrtolPoints.add(new Vector3f(0, extrude + bevelDepth, 0));
if (cyclic) {
conrtolPoints.add(new Vector3f(0, extrude + bevelDepth, handlerLength));
conrtolPoints.add(new Vector3f(0, extrude + handlerLength, bevelDepth));
conrtolPoints.add(new Vector3f(0, extrude, bevelDepth));
conrtolPoints.add(new Vector3f(0, extrude - handlerLength, bevelDepth));
if (extrude > 0) {
conrtolPoints.add(new Vector3f(0, -extrude + handlerLength, bevelDepth));
conrtolPoints.add(new Vector3f(0, -extrude, bevelDepth));
conrtolPoints.add(new Vector3f(0, -extrude - handlerLength, bevelDepth));
}
conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, handlerLength));
conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, 0));
}
} else {
if (extrude > 0) {
if (isBack) {
conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, 0));
conrtolPoints.add(new Vector3f(0, -extrude - bevelDepth, -handlerLength));
conrtolPoints.add(new Vector3f(0, -extrude - handlerLength, -bevelDepth));
}
conrtolPoints.add(new Vector3f(0, -extrude, -bevelDepth));
conrtolPoints.add(new Vector3f(0, -extrude + handlerLength, -bevelDepth));
conrtolPoints.add(new Vector3f(0, extrude - handlerLength, -bevelDepth));
conrtolPoints.add(new Vector3f(0, extrude, -bevelDepth));
if (isFront) {
conrtolPoints.add(new Vector3f(0, extrude + handlerLength, -bevelDepth));
conrtolPoints.add(new Vector3f(0, extrude + bevelDepth, -handlerLength));
conrtolPoints.add(new Vector3f(0, extrude + bevelDepth, 0));
}
} else {
if (isFront && isBack) {
conrtolPoints.add(new Vector3f(0, -bevelDepth, 0));
conrtolPoints.add(new Vector3f(0, -bevelDepth, -handlerLength));
conrtolPoints.add(new Vector3f(0, -handlerLength, -bevelDepth));
conrtolPoints.add(new Vector3f(0, 0, -bevelDepth));
conrtolPoints.add(new Vector3f(0, handlerLength, -bevelDepth));
conrtolPoints.add(new Vector3f(0, bevelDepth, -handlerLength));
conrtolPoints.add(new Vector3f(0, bevelDepth, 0));
} else {
if (isBack) {
conrtolPoints.add(new Vector3f(0, -bevelDepth, 0));
conrtolPoints.add(new Vector3f(0, -bevelDepth, -handlerLength));
conrtolPoints.add(new Vector3f(0, -handlerLength, -bevelDepth));
conrtolPoints.add(new Vector3f(0, 0, -bevelDepth));
} else {
conrtolPoints.add(new Vector3f(0, 0, -bevelDepth));
conrtolPoints.add(new Vector3f(0, handlerLength, -bevelDepth));
conrtolPoints.add(new Vector3f(0, bevelDepth, -handlerLength));
conrtolPoints.add(new Vector3f(0, bevelDepth, 0));
}
}
}
}
bevelCurve = new Curve(new Spline(SplineType.Bezier, conrtolPoints, 0, false), bevResol);
} else if (extrude > 0.0f) {
Spline bevelSpline = new Spline(SplineType.Linear, new Vector3f[] { new Vector3f(0, extrude, 0), new Vector3f(0, -extrude, 0) }, 1, false);
bevelCurve = new Curve(bevelSpline, bevResol);
}
if (bevelCurve != null) {
bevelObject = new CurvesTemporalMesh(blenderContext);
FloatBuffer vertsBuffer = (FloatBuffer) bevelCurve.getBuffer(Type.Position).getData();
Vector3f[] verts = BufferUtils.getVector3Array(vertsBuffer);
if (cyclic) {
// get rid of the last vertex which is identical to the first one
verts = Arrays.copyOf(verts, verts.length - 1);
}
bevelObject.beziers.add(new BezierLine(verts, 0, false, cyclic));
}
}
return bevelObject;
}
use of com.jme3.scene.plugins.blender.file.Pointer in project jmonkeyengine by jMonkeyEngine.
the class CurvesTemporalMesh method loadBezierCurve.
/**
* The methods loads the bezier curve from the given structure.
* @param nurbStructure
* the structure containing a single curve definition
* @param materialIndex
* the index of this segment's material
* @throws BlenderFileException
* an exception is thrown when problems with reading occur
*/
private void loadBezierCurve(Structure nurbStructure, int materialIndex) throws BlenderFileException {
Pointer pBezierTriple = (Pointer) nurbStructure.getFieldValue("bezt");
if (pBezierTriple.isNotNull()) {
int resolution = ((Number) nurbStructure.getFieldValue("resolu")).intValue();
boolean cyclic = (((Number) nurbStructure.getFieldValue("flagu")).intValue() & 0x01) != 0;
boolean smooth = (((Number) nurbStructure.getFieldValue("flag")).intValue() & FLAG_SMOOTH) != 0;
// creating the curve object
BezierCurve bezierCurve = new BezierCurve(0, pBezierTriple.fetchData(), 3, blenderContext.getBlenderKey().isFixUpAxis());
List<Vector3f> controlPoints = bezierCurve.getControlPoints();
if (cyclic) {
// copy the first three points at the end
for (int i = 0; i < 3; ++i) {
controlPoints.add(controlPoints.get(i));
}
}
// removing the first and last handles
controlPoints.remove(0);
controlPoints.remove(controlPoints.size() - 1);
// creating curve
Curve curve = new Curve(new Spline(SplineType.Bezier, controlPoints, 0, false), resolution);
FloatBuffer vertsBuffer = (FloatBuffer) curve.getBuffer(Type.Position).getData();
beziers.add(new BezierLine(BufferUtils.getVector3Array(vertsBuffer), materialIndex, smooth, cyclic));
}
}
use of com.jme3.scene.plugins.blender.file.Pointer in project jmonkeyengine by jMonkeyEngine.
the class Point method loadAll.
/**
* Loads all points of the mesh that do not belong to any edge.
* @param meshStructure
* the mesh structure
* @return a list of points
* @throws BlenderFileException
* an exception is thrown when problems with file reading occur
*/
public static List<Point> loadAll(Structure meshStructure) throws BlenderFileException {
LOGGER.log(Level.FINE, "Loading all points that do not belong to any edge from mesh: {0}", meshStructure.getName());
List<Point> result = new ArrayList<Point>();
Pointer pMEdge = (Pointer) meshStructure.getFieldValue("medge");
if (pMEdge.isNotNull()) {
int count = ((Number) meshStructure.getFieldValue("totvert")).intValue();
Set<Integer> unusedVertices = new HashSet<Integer>(count);
for (int i = 0; i < count; ++i) {
unusedVertices.add(i);
}
List<Structure> edges = pMEdge.fetchData();
for (Structure edge : edges) {
unusedVertices.remove(((Number) edge.getFieldValue("v1")).intValue());
unusedVertices.remove(((Number) edge.getFieldValue("v2")).intValue());
}
for (Integer unusedIndex : unusedVertices) {
result.add(new Point(unusedIndex));
}
}
LOGGER.log(Level.FINE, "Loaded {0} points.", result.size());
return result;
}
Aggregations