--- /dev/null
+/*******************************************************************************\r
+ * Copyright (c) 2007- VTT Technical Research Centre of Finland.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.base;\r
+\r
+import java.nio.ByteBuffer;\r
+import java.util.HashMap;\r
+import java.util.Map;\r
+\r
+import org.eclipse.swt.graphics.ImageData;\r
+import org.simantics.db.Graph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.proconf.g3d.Resources;\r
+import org.simantics.proconf.g3d.stubs.ImageTexture;\r
+import org.simantics.proconf.g3d.stubs.TextureCoordinateGenerator;\r
+import org.simantics.proconf.image.interfaces.IImage;\r
+import org.simantics.proconf.image.interfaces.IImageFactory;\r
+import org.simantics.utils.ui.ErrorLogger;\r
+import org.simantics.utils.ui.gfx.ImageUtils;\r
+import org.simantics.utils.ui.gfx.PixelDimension;\r
+\r
+import com.jme.image.Image;\r
+import com.jme.image.Texture;\r
+\r
+/**\r
+ * Caches resource based textures.\r
+ * TODO : use queries to update textures, now textures are read once and cannot be updated\r
+ * TODO : either use shared context or use separate cache for each editor\r
+ * TODO : ShapeNode implementation won't use release texture yet\r
+ * TODO : Texture is released when reference count goes to zero; we probably want to wait for a while before texture is released because it might be used again.\r
+ * TODO : Support for other types of textures (not just pattern texture, preferably extensible interface)\r
+ * \r
+ * @author Marko Luukkainen <Marko.Luukkainen@vtt.fi>\r
+ *\r
+ */\r
+public class ResourceTextureCache {\r
+ \r
+ public static PixelDimension DEFAULT_SIZE = new PixelDimension(128,128);\r
+ \r
+ private static ResourceTextureCache instance = new ResourceTextureCache();\r
+ \r
+ private Map<Resource,Image> images = new HashMap<Resource, Image>();\r
+ private Map<Resource,Integer> imageReferences = new HashMap<Resource, Integer>();\r
+ \r
+ private Map<Resource,Texture> textures = new HashMap<Resource, Texture>();\r
+ private Map<Resource,Integer> textureReferences = new HashMap<Resource, Integer>();\r
+ \r
+ \r
+ private ResourceTextureCache() {\r
+ \r
+ }\r
+ \r
+ public Texture loadTexture(Graph g, Resource res) {\r
+ Texture t = textures.get(res);\r
+ if (t == null) {\r
+ ImageTexture it = new ImageTexture(g,res);\r
+ org.simantics.image.stubs.Image pattern = it.getImage();\r
+ Image image = loadImage(g, pattern.getResource());\r
+\r
+ if (image == null) {\r
+ return null;\r
+ }\r
+ t = new Texture();\r
+ t.setImage(image);\r
+ \r
+ \r
+ t.setFilter(com.jme.image.Texture.FM_LINEAR);\r
+ t.setMipmapState(com.jme.image.Texture.MM_LINEAR);\r
+ t.setApply(Texture.AM_COMBINE);\r
+ t.setCombineFuncRGB(Texture.ACF_MODULATE);\r
+ t.setCombineScaleRGB(2.f);\r
+\r
+ //t.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T);\r
+ \r
+ TextureCoordinateGenerator gen = it.getTextureCoordinateGenerator();\r
+ setTextureCoordGenerator(gen, t);\r
+ textures.put(res, t);\r
+ }\r
+ addTextureReference(res);\r
+ return t;\r
+ }\r
+ \r
+ public void releaseTexture(Graph g, Resource res) {\r
+ Integer i = textureReferences.get(res);\r
+ if (i != null) {\r
+ i = i - 1;\r
+ if (i == 0) {\r
+ Texture t = textures.get(res);\r
+ ImageTexture it = new ImageTexture(g,res);\r
+ org.simantics.image.stubs.Image pattern = it.getImage();\r
+ releaseImage(pattern.getResource());\r
+ t.setImage(null);\r
+ textureReferences.remove(res);\r
+ //FIXME : release the texture\r
+ } else {\r
+ textureReferences.put(res, i);\r
+ }\r
+ \r
+ } else {\r
+ throw new RuntimeException("Cannot released texture that does not exist " + res);\r
+ }\r
+ }\r
+ \r
+ public Image loadImage(Graph g, Resource res) {\r
+ Image image = images.get(res);\r
+ if (image == null) {\r
+ org.simantics.image.stubs.Image pattern = new org.simantics.image.stubs.Image(g,res);\r
+ IImageFactory f = org.simantics.proconf.image.ImageUtils.getImageFactoryForResource(g,pattern.getResource());\r
+ try {\r
+ IImage p = f.createImageForResource(g,pattern.getResource());\r
+ PixelDimension pd = p.getDimensions().getPixelDimension();\r
+ if (pd==null) pd = DEFAULT_SIZE;\r
+ ImageData data = p.rasterize(pd.getWidth(), pd.getHeight());\r
+ image = getImage(data);\r
+ images.put(res, image);\r
+ \r
+ } catch (Exception e) {\r
+ ErrorLogger.defaultLogError("Cannor create pattern texture for resource " + pattern, e);\r
+ return null;\r
+ }\r
+ }\r
+ addImageReference(res);\r
+ return image;\r
+ \r
+ }\r
+ \r
+ private void addTextureReference(Resource res) {\r
+ Integer i = textureReferences.get(res);\r
+ if (i != null) {\r
+ imageReferences.put(res, i + 1);\r
+ } else {\r
+ imageReferences.put(res, 1);\r
+ }\r
+ }\r
+ \r
+ private void addImageReference(Resource res) {\r
+ Integer i = imageReferences.get(res);\r
+ if (i != null) {\r
+ imageReferences.put(res, i + 1);\r
+ } else {\r
+ imageReferences.put(res, 1);\r
+ }\r
+ }\r
+ \r
+ public void releaseImage(Resource res) {\r
+ Integer i = imageReferences.get(res);\r
+ if (i != null) {\r
+ i = i - 1;\r
+ if (i == 0) {\r
+ Image image = images.get(res);\r
+ image.getData().clear();\r
+ image.setData(null);\r
+ images.remove(res);\r
+ imageReferences.remove(res);\r
+ } else {\r
+ imageReferences.put(res, i);\r
+ }\r
+ } else {\r
+ throw new RuntimeException("Cannot release image that does not exist.");\r
+ }\r
+ }\r
+ \r
+ public static ResourceTextureCache getInstance() {\r
+ return instance;\r
+ }\r
+ \r
+ public static Image getImage(ImageData imageData) {\r
+ int width = imageData.width;\r
+ int height = imageData.height;\r
+ int type = 0;\r
+ \r
+ int components = 3;\r
+ \r
+ type = Image.RGB888;\r
+ if (imageData.alphaData != null) {\r
+ type = Image.RGBA8888;\r
+ components = 4;\r
+ }\r
+ \r
+ ByteBuffer buf = ByteBuffer.allocateDirect(components * width * height);\r
+ ImageUtils.convertToRGBA(imageData, buf); \r
+ return new Image(type,width,height,buf);\r
+ }\r
+ \r
+ \r
+ public static void setTextureCoordGenerator(TextureCoordinateGenerator gen, com.jme.image.Texture texture) {\r
+ if (gen == null)\r
+ return ;\r
+\r
+ //g3dResource.\r
+ if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_sphere))\r
+ texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_SPHERE);\r
+ else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_eyelinear))\r
+ texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_EYE_LINEAR);\r
+ else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_objectlinear))\r
+ texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_OBJECT_LINEAR);\r
+ else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_normal))\r
+ ErrorLogger.getDefault().logWarning("JME doesn't support normal texture coordinate generation", null);\r
+ else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_reflection))\r
+ ErrorLogger.getDefault().logWarning("JME doesn't support reflection texture coordinate generation", null);\r
+ else\r
+ ErrorLogger.getDefault().logWarning("Unsupported TexGen type " + gen.getName(), null);\r
+ }\r
+ \r
+ public void clear() {\r
+ for (Image i : images.values())\r
+ i.setData(null);\r
+ for (Texture t : textures.values())\r
+ t.setImage(null);\r
+ imageReferences.clear();\r
+ textureReferences.clear();\r
+ images.clear();\r
+ textures.clear();\r
+ \r
+ }\r
+\r
+}\r