package com.jme3.scene.plugins.blender.cameras; import java.util.logging.Level; import java.util.logging.Logger; import com.jme3.math.FastMath; import com.jme3.renderer.Camera; import com.jme3.scene.plugins.blender.AbstractBlenderHelper; import com.jme3.scene.plugins.blender.BlenderContext; import com.jme3.scene.plugins.blender.file.BlenderFileException; import com.jme3.scene.plugins.blender.file.Structure; /** * A class that is used to load cameras into the scene. * @author Marcin Roguski */ public class CameraHelper extends AbstractBlenderHelper { private static final Logger LOGGER = Logger.getLogger(CameraHelper.class.getName()); protected static final int DEFAULT_CAM_WIDTH = 640; protected static final int DEFAULT_CAM_HEIGHT = 480; /** * This constructor parses the given blender version and stores the result. Some functionalities may differ in * different blender versions. * @param blenderVersion * the version read from the blend file * @param blenderContext * the blender context */ public CameraHelper(String blenderVersion, BlenderContext blenderContext) { super(blenderVersion, blenderContext); } /** * This method converts the given structure to jme camera. * * @param structure * camera structure * @return jme camera object * @throws BlenderFileException * an exception is thrown when there are problems with the * blender file */ public Camera toCamera(Structure structure, BlenderContext blenderContext) throws BlenderFileException { if (blenderVersion >= 250) { return this.toCamera250(structure, blenderContext.getSceneStructure()); } else { return this.toCamera249(structure); } } /** * This method converts the given structure to jme camera. Should be used form blender 2.5+. * * @param structure * camera structure * @param sceneStructure * scene structure * @return jme camera object * @throws BlenderFileException * an exception is thrown when there are problems with the * blender file */ private Camera toCamera250(Structure structure, Structure sceneStructure) throws BlenderFileException { int width = DEFAULT_CAM_WIDTH; int height = DEFAULT_CAM_HEIGHT; if (sceneStructure != null) { Structure renderData = (Structure) sceneStructure.getFieldValue("r"); width = ((Number) renderData.getFieldValue("xsch")).shortValue(); height = ((Number) renderData.getFieldValue("ysch")).shortValue(); } Camera camera = new Camera(width, height); 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); type = 0; } // type==0 - perspective; type==1 - orthographic; perspective is used as default camera.setParallelProjection(type == 1); float aspect = width / (float) height; float fovY; // Vertical field of view in degrees float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue(); float clipend = ((Number) structure.getFieldValue("clipend")).floatValue(); if (type == 0) { // Convert lens MM to vertical degrees in fovY, see Blender rna_Camera_angle_get() // Default sensor size prior to 2.60 was 32. float sensor = 32.0f; boolean sensorVertical = false; Number sensorFit = (Number) structure.getFieldValue("sensor_fit"); if (sensorFit != null) { // If sensor_fit is vert (2), then sensor_y is used sensorVertical = sensorFit.byteValue() == 2; String sensorName = "sensor_x"; if (sensorVertical) { sensorName = "sensor_y"; } sensor = ((Number) structure.getFieldValue(sensorName)).floatValue(); } float focalLength = ((Number) structure.getFieldValue("lens")).floatValue(); float fov = 2.0f * FastMath.atan(sensor / 2.0f / focalLength); if (sensorVertical) { fovY = fov * FastMath.RAD_TO_DEG; } else { // Convert fov from horizontal to vertical fovY = 2.0f * FastMath.atan(FastMath.tan(fov / 2.0f) / aspect) * FastMath.RAD_TO_DEG; } } else { // This probably is not correct. fovY = ((Number) structure.getFieldValue("ortho_scale")).floatValue(); } camera.setFrustumPerspective(fovY, aspect, clipsta, clipend); camera.setName(structure.getName()); return camera; } /** * This method converts the given structure to jme camera. Should be used form blender 2.49. * * @param structure * camera structure * @return jme camera object * @throws BlenderFileException * an exception is thrown when there are problems with the * blender file */ private Camera toCamera249(Structure structure) throws BlenderFileException { Camera camera = new Camera(DEFAULT_CAM_WIDTH, DEFAULT_CAM_HEIGHT); 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); type = 0; } // type==0 - perspective; type==1 - orthographic; perspective is used as default camera.setParallelProjection(type == 1); float aspect = 0; float clipsta = ((Number) structure.getFieldValue("clipsta")).floatValue(); float clipend = ((Number) structure.getFieldValue("clipend")).floatValue(); if (type == 0) { aspect = ((Number) structure.getFieldValue("lens")).floatValue(); } else { aspect = ((Number) structure.getFieldValue("ortho_scale")).floatValue(); } camera.setFrustumPerspective(aspect, camera.getWidth() / camera.getHeight(), clipsta, clipend); camera.setName(structure.getName()); return camera; } }