1/*
2 * Copyright (c) 2009-2010 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 */
32package com.jme3.scene.plugins.blender;
33
34import com.jme3.asset.AssetLoader;
35import com.jme3.asset.BlenderKey.FeaturesToLoad;
36import com.jme3.asset.BlenderKey.WorldData;
37import com.jme3.light.AmbientLight;
38import com.jme3.light.Light;
39import com.jme3.material.Material;
40import com.jme3.math.ColorRGBA;
41import com.jme3.renderer.Camera;
42import com.jme3.scene.Geometry;
43import com.jme3.scene.Node;
44import com.jme3.scene.Spatial;
45import com.jme3.scene.plugins.blender.cameras.CameraHelper;
46import com.jme3.scene.plugins.blender.exceptions.BlenderFileException;
47import com.jme3.scene.plugins.blender.file.Pointer;
48import com.jme3.scene.plugins.blender.file.Structure;
49import com.jme3.scene.plugins.blender.lights.LightHelper;
50import com.jme3.scene.plugins.blender.materials.MaterialHelper;
51import com.jme3.scene.plugins.blender.meshes.MeshHelper;
52import com.jme3.scene.plugins.blender.objects.ObjectHelper;
53import java.util.List;
54import java.util.logging.Level;
55import java.util.logging.Logger;
56
57/**
58 * This class converts blender file blocks into jMonkeyEngine data structures.
59 * @author Marcin Roguski (Kaelthas)
60 */
61/* package */ abstract class AbstractBlenderLoader implements AssetLoader {
62	private static final Logger LOGGER = Logger.getLogger(AbstractBlenderLoader.class.getName());
63
64	protected BlenderContext	blenderContext;
65
66	/**
67	 * This method converts the given structure to a scene node.
68	 * @param structure
69	 *        structure of a scene
70	 * @return scene's node
71	 */
72	public Node toScene(Structure structure) {
73		if ((blenderContext.getBlenderKey().getFeaturesToLoad() & FeaturesToLoad.SCENES) == 0) {
74			return null;
75		}
76		Node result = new Node(structure.getName());
77		try {
78			List<Structure> base = ((Structure)structure.getFieldValue("base")).evaluateListBase(blenderContext);
79			for(Structure b : base) {
80				Pointer pObject = (Pointer) b.getFieldValue("object");
81				if(pObject.isNotNull()) {
82					Structure objectStructure = pObject.fetchData(blenderContext.getInputStream()).get(0);
83					Object object = this.toObject(objectStructure);
84					if(object instanceof Spatial && ((Spatial) object).getParent()==null) {
85						result.attachChild((Spatial) object);
86					} else if(object instanceof Light) {
87						result.addLight((Light)object);
88					}
89				}
90			}
91		} catch (BlenderFileException e) {
92			LOGGER.log(Level.SEVERE, e.getLocalizedMessage(), e);
93		}
94		return result;
95	}
96
97	/**
98	 * This method converts the given structure to a camera.
99	 * @param structure
100	 *        structure of a camera
101	 * @return camera's node
102	 */
103	public Camera toCamera(Structure structure) throws BlenderFileException {
104		CameraHelper cameraHelper = blenderContext.getHelper(CameraHelper.class);
105		if (cameraHelper.shouldBeLoaded(structure, blenderContext)) {
106			return cameraHelper.toCamera(structure);
107		}
108		return null;
109	}
110
111	/**
112	 * This method converts the given structure to a light.
113	 * @param structure
114	 *        structure of a light
115	 * @return light's node
116	 */
117	public Light toLight(Structure structure) throws BlenderFileException {
118		LightHelper lightHelper = blenderContext.getHelper(LightHelper.class);
119		if (lightHelper.shouldBeLoaded(structure, blenderContext)) {
120			return lightHelper.toLight(structure, blenderContext);
121		}
122		return null;
123	}
124
125	/**
126	 * This method converts the given structure to a node.
127	 * @param structure
128	 *        structure of an object
129	 * @return object's node
130	 */
131	public Object toObject(Structure structure) throws BlenderFileException {
132		ObjectHelper objectHelper = blenderContext.getHelper(ObjectHelper.class);
133		if (objectHelper.shouldBeLoaded(structure, blenderContext)) {
134			return objectHelper.toObject(structure, blenderContext);
135		}
136		return null;
137	}
138
139	/**
140	 * This method converts the given structure to a list of geometries.
141	 * @param structure
142	 *        structure of a mesh
143	 * @return list of geometries
144	 */
145	public List<Geometry> toMesh(Structure structure) throws BlenderFileException {
146		MeshHelper meshHelper = blenderContext.getHelper(MeshHelper.class);
147		if (meshHelper.shouldBeLoaded(structure, blenderContext)) {
148			return meshHelper.toMesh(structure, blenderContext);
149		}
150		return null;
151	}
152
153	/**
154	 * This method converts the given structure to a material.
155	 * @param structure
156	 *        structure of a material
157	 * @return material's node
158	 */
159	public Material toMaterial(Structure structure) throws BlenderFileException {
160		MaterialHelper materialHelper = blenderContext.getHelper(MaterialHelper.class);
161		if (materialHelper.shouldBeLoaded(structure, blenderContext)) {
162			return materialHelper.toMaterial(structure, blenderContext);
163		}
164		return null;
165	}
166
167	/**
168	 * This method returns the data read from the WORLD file block. The block contains data that can be stored as
169	 * separate jme features and therefore cannot be returned as a single jME scene feature.
170	 * @param structure
171	 *        the structure with WORLD block data
172	 * @return data read from the WORLD block that can be added to the scene
173	 */
174	public WorldData toWorldData(Structure structure) {
175		WorldData result = new WorldData();
176
177		// reading ambient light
178		AmbientLight ambientLight = new AmbientLight();
179		float ambr = ((Number) structure.getFieldValue("ambr")).floatValue();
180		float ambg = ((Number) structure.getFieldValue("ambg")).floatValue();
181		float ambb = ((Number) structure.getFieldValue("ambb")).floatValue();
182		ambientLight.setColor(new ColorRGBA(ambr, ambg, ambb, 0.0f));
183		result.setAmbientLight(ambientLight);
184
185		return result;
186	}
187}
188