@Kaelthas the Blender importer camera loader doesn’t currently properly set the field of view or aspect of the camera - so the scene looks different than how it looks through the camera in Blender.
The camera “lens” SDNA field is in millimeters, it’s currently used as the aspect ratio which doesn’t make sense (e.g. the default value is 35mm).
This patch uses “lens” and “sensor_fit” along with “sensor_x” and “sensor_y” to compute the field of view in degrees. JME camera uses a vertical FoV, Blender uses horizontal by default (depending on “sensor_fit”). So to convert from horizontal to vertical, we need the actual camera viewport aspect ratio (“xsch” / “ysch”) which Blender stores in the scenes RenderData structure.
I wasn’t sure how to deal with “ortho_scale” for a parallel camera - I don’t think it’s currently being handled properly, and this patch doesn’t fix it.
[patch]diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderLoader.java b/engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderLoader.java
index 0c8d7d7…43489ac 100644
— a/engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderLoader.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/AbstractBlenderLoader.java
@@ -106,7 +106,7 @@ import com.jme3.scene.plugins.blender.objects.ObjectHelper;
public CameraNode toCamera(Structure structure) throws BlenderFileException {
CameraHelper cameraHelper = blenderContext.getHelper(CameraHelper.class);
if (cameraHelper.shouldBeLoaded(structure, blenderContext)) {
-
return cameraHelper.toCamera(structure);<br />
-
return cameraHelper.toCamera(structure, blenderContext);<br />
}
return null;
}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java
index 5b5c57e…979353e 100644
— a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderContext.java
@@ -74,6 +74,8 @@ public class BlenderContext {
private BlenderKey blenderKey;
/** The header of the file block. */
private DnaBlockData dnaBlockData;
- /** The scene structure. */
- private Structure sceneStructure;
/** The input stream of the blend file. /
private BlenderInputStream inputStream;
/* The asset manager. */
@@ -174,6 +176,24 @@ public class BlenderContext {
public DnaBlockData getDnaBlockData() {
return dnaBlockData;
}
- /**
-
- This method sets the scene structure data.
- This method sets the scene structure data.
- *
-
-
@param sceneStructure
-
@param sceneStructure
-
-
the scene structure data<br />
-
- */
- public void setSceneStructure(Structure sceneStructure) {
-
this.sceneStructure = sceneStructure;<br />
- }
+
- /**
-
- This method returns the scene structure data.
- This method returns the scene structure data.
- *
-
-
@return the scene structure data
-
@return the scene structure data
- */
- public Structure getSceneStructure() {
-
return sceneStructure;<br />
- }
/**
- This method returns the asset manager.
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java
index afad7ff…7829116 100644
— a/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/BlenderLoader.java
@@ -215,15 +215,19 @@ public class BlenderLoader extends AbstractBlenderLoader {
if (!fileBlock.isDnaBlock()) {
blocks.add(fileBlock);
// save the scene’s file block
-
if (fileBlock.getCode() == FileBlockHeader.BLOCK_SC00 && blenderKey.getLayersToLoad() < 0) {<br />
-
if (fileBlock.getCode() == FileBlockHeader.BLOCK_SC00) {<br />
sceneFileBlock = fileBlock;
}
}
} while (!fileBlock.isLastBlock());
// VERIFY LAYERS TO BE LOADED BEFORE LOADING FEATURES
if (sceneFileBlock != null) {
-
int lay = ((Number) sceneFileBlock.getStructure(blenderContext).getFieldValue("lay")).intValue();<br />
-
blenderContext.getBlenderKey().setLayersToLoad(lay);// load only current layer<br />
-
Structure sceneStructure = sceneFileBlock.getStructure(blenderContext);<br />
-
if (blenderKey.getLayersToLoad() < 0) {<br />
-
int lay = ((Number) sceneStructure.getFieldValue("lay")).intValue();<br />
-
blenderContext.getBlenderKey().setLayersToLoad(lay);// load only current layer<br />
-
}<br />
-
blenderContext.setSceneStructure(sceneStructure);<br />
}
}
}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java
index ae028ee…5aeb74d 100644
— a/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/cameras/CameraHelper.java
@@ -1,6 +1,7 @@
package com.jme3.scene.plugins.blender.cameras;
import com.jme3.asset.BlenderKey.FeaturesToLoad;
+import com.jme3.math.FastMath;
import com.jme3.renderer.Camera;
import com.jme3.scene.CameraNode;
import com.jme3.scene.plugins.blender.AbstractBlenderHelper;
@@ -42,9 +43,9 @@ public class CameraHelper extends AbstractBlenderHelper {
-
an exception is thrown when there are problems with the<br />
-
blender file<br />
*/
- public CameraNode toCamera(Structure structure) throws BlenderFileException {
- public CameraNode toCamera(Structure structure, BlenderContext blenderContext) throws BlenderFileException {
if (blenderVersion >= 250) {
-
return this.toCamera250(structure);<br />
-
return this.toCamera250(structure, blenderContext.getSceneStructure());<br />
} else {
return this.toCamera249(structure);
}
@@ -55,13 +56,22 @@ public class CameraHelper extends AbstractBlenderHelper {
*
-
@param structure
-
camera structure<br />
-
-
@param sceneStructure
-
@param sceneStructure
-
-
scene structure<br />
-
-
@return jme camera object
-
@throws BlenderFileException
-
an exception is thrown when there are problems with the<br />
-
blender file<br />
*/
- private CameraNode toCamera250(Structure structure) throws BlenderFileException {
-
Camera camera = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT);<br />
- private CameraNode toCamera250(Structure structure, Structure sceneStructure) throws BlenderFileException {
-
int width = DEFAULT_CAM_WIDTH;<br />
-
int height = DEFAULT_CAM_HEIGHT;<br />
-
if (sceneStructure != null) {<br />
-
Structure renderData = (Structure)sceneStructure.getFieldValue("r");<br />
-
width = ((Number)renderData.getFieldValue("xsch")).shortValue();<br />
-
height = ((Number)renderData.getFieldValue("ysch")).shortValue();<br />
-
}<br />
-
Camera camera = new Camera(width, height);<br />
int type = ((Number) structure.getFieldValue("type")).intValue();
if (type != 0 && type != 1) {
LOGGER.log(Level.WARNING, "Unknown camera type: {0}. Perspective camera is being used!", type);
@@ -69,15 +79,31 @@ public class CameraHelper extends AbstractBlenderHelper {
}
//type==0 - perspective; type==1 - orthographic; perspective is used as default
camera.setParallelProjection(type == 1);
-
float aspect = 0;<br />
-
float aspect = width / (float)height;<br />
-
float fovY; // Vertical field of view in degrees<br />
float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue();
float clipend = ((Number) structure.getFieldValue("clipend")).floatValue();
if (type == 0) {
-
aspect = ((Number) structure.getFieldValue("lens")).floatValue();<br />
-
// Convert lens MM to vertical degrees in fovY, see Blender rna_Camera_angle_get()<br />
-
// If sensor_fit is vert (2), then sensor_y is used<br />
-
boolean sensorVertical = ((Byte)structure.getFieldValue("sensor_fit")).byteValue() == 2;<br />
-
String sensorName = "sensor_x";<br />
-
if (sensorVertical) {<br />
-
sensorName = "sensor_y";<br />
-
}<br />
-
float focalLength = ((Number) structure.getFieldValue("lens")).floatValue();<br />
-
float sensor = ((Number) structure.getFieldValue(sensorName)).floatValue();<br />
-
float fov = 2.0f * FastMath.atan((sensor / 2.0f) / focalLength);<br />
-
if (sensorVertical) {<br />
-
fovY = fov * FastMath.RAD_TO_DEG;<br />
-
} else {<br />
-
// Convert fov from horizontal to vertical<br />
-
fovY = 2.0f * FastMath.atan(FastMath.tan(fov / 2.0f) / aspect) * FastMath.RAD_TO_DEG;<br />
-
}<br />
} else {
-
aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue();<br />
-
fovY = ((Number) structure.getFieldValue("ortho_scale")).floatValue();//XXX<br />
}
-
camera.setFrustumPerspective(45, aspect, clipsta, clipend);<br />
-
camera.setFrustumPerspective(fovY, aspect, clipsta, clipend);<br />
return new CameraNode(null, camera);
}
diff --git a/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java b/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java
index c0058eb…e430d03 100644
— a/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java
+++ b/engine/src/blender/com/jme3/scene/plugins/blender/objects/ObjectHelper.java
@@ -206,7 +206,7 @@ public class ObjectHelper extends AbstractBlenderHelper {
if(pCamera.isNotNull()) {
CameraHelper cameraHelper = blenderContext.getHelper(CameraHelper.class);
List<Structure> camerasArray = pCamera.fetchData(blenderContext.getInputStream());
-
CameraNode camera = cameraHelper.toCamera(camerasArray.get(0));<br />
-
CameraNode camera = cameraHelper.toCamera(camerasArray.get(0), blenderContext);<br />
camera.setName(name);
camera.setLocalTransform(t);
result = camera;
[/patch]