]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - org.simantics.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java
git-svn-id: https://www.simantics.org/svn/simantics/3d/trunk@22280 ac1ea38d-2e2b...
[simantics/3d.git] / org.simantics.g3d / src / org / simantics / proconf / g3d / base / ResourceTextureCache.java
diff --git a/org.simantics.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java b/org.simantics.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java
new file mode 100644 (file)
index 0000000..10ff6ce
--- /dev/null
@@ -0,0 +1,224 @@
+/*******************************************************************************\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