]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java
git-svn-id: https://www.simantics.org/svn/simantics/3d/branches/dev@7251 ac1ea38d...
[simantics/3d.git] / org.simantics.proconf.g3d / src / org / simantics / proconf / g3d / base / ResourceTextureCache.java
1 package org.simantics.proconf.g3d.base;\r
2 \r
3 import java.nio.ByteBuffer;\r
4 import java.util.HashMap;\r
5 import java.util.Map;\r
6 \r
7 import org.eclipse.swt.graphics.ImageData;\r
8 import org.simantics.db.Graph;\r
9 import org.simantics.db.Resource;\r
10 import org.simantics.proconf.g3d.Resources;\r
11 import org.simantics.proconf.g3d.stubs.ImageTexture;\r
12 import org.simantics.proconf.g3d.stubs.TextureCoordinateGenerator;\r
13 import org.simantics.proconf.image.interfaces.IImage;\r
14 import org.simantics.proconf.image.interfaces.IImageFactory;\r
15 import org.simantics.utils.ErrorLogger;\r
16 import org.simantics.utils.ui.gfx.ImageUtils;\r
17 import org.simantics.utils.ui.gfx.PixelDimension;\r
18 \r
19 import com.jme.image.Image;\r
20 import com.jme.image.Texture;\r
21 import com.jme.util.TextureManager;\r
22 \r
23 /**\r
24  * Caches resource based textures.\r
25  * TODO : use queries to update textures, now textures are read once and cannot be updated\r
26  * TODO : either use shared context or use separate cache for each editor\r
27  * TODO : ShapeNode implementation won't use release texture yet\r
28  * 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
29  * \r
30  * @author Marko Luukkainen <Marko.Luukkainen@vtt.fi>\r
31  *\r
32  */\r
33 public class ResourceTextureCache {\r
34         \r
35         public static PixelDimension DEFAULT_SIZE = new PixelDimension(128,128);\r
36         \r
37         private static ResourceTextureCache instance = new ResourceTextureCache();\r
38         \r
39         private Map<Resource,Image> images = new HashMap<Resource, Image>();\r
40         private Map<Resource,Integer> imageReferences = new HashMap<Resource, Integer>();\r
41         \r
42         private Map<Resource,Texture> textures = new HashMap<Resource, Texture>();\r
43         private Map<Resource,Integer> textureReferences = new HashMap<Resource, Integer>();\r
44         \r
45         \r
46         private ResourceTextureCache() {\r
47                 \r
48         }\r
49         \r
50         public Texture loadTexture(Graph g, Resource res) {\r
51                 Texture t = textures.get(res);\r
52                 if (t == null) {\r
53                         ImageTexture it = new ImageTexture(g,res);\r
54                         org.simantics.image.stubs.Image pattern = it.getImage();\r
55                         Image image = loadImage(g, pattern.getResource());\r
56 //                      image.getData().rewind();\r
57 //                      while (image.getData().hasRemaining())\r
58 //                              image.getData().put((byte)(Math.random()*256.0 - 127.0));\r
59                         if (image == null) {\r
60                                 return null;\r
61                         }\r
62                         t = new Texture();\r
63                         t.setImage(image);\r
64                         \r
65                         //t = TextureManager.loadTexture(image, Texture.MM_LINEAR, Texture.FM_LINEAR);\r
66 //                      t.setImageLocation(res.toString());\r
67 //                      URL url = FileLocator.find(com.jme.eclipse.Activator.getDefault().getBundle(),new Path("data/texture/clouds.png"),null);\r
68 //              t = TextureManager.loadTexture(url, Texture.MM_LINEAR, Texture.FM_LINEAR);\r
69                 \r
70                         t.setFilter(com.jme.image.Texture.FM_LINEAR);\r
71                 t.setMipmapState(com.jme.image.Texture.MM_LINEAR);\r
72                 t.setApply(Texture.AM_COMBINE);\r
73                 t.setCombineFuncRGB(Texture.ACF_MODULATE);\r
74                 t.setCombineScaleRGB(2.f);\r
75 \r
76                 //t.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T);\r
77                         \r
78                         TextureCoordinateGenerator gen = it.getTextureCoordinateGenerator();\r
79                         setTextureCoordGenerator(gen, t);\r
80                         textures.put(res, t);\r
81                 }\r
82                 addTextureReference(res);\r
83                 return t;\r
84         }\r
85         \r
86         public void releaseTexture(Graph g, Resource res) {\r
87                 Integer i = textureReferences.get(res);\r
88                 if (i != null) {\r
89                         i = i - 1;\r
90                         if (i == 0) {\r
91                                 Texture t = textures.get(res);\r
92                                 ImageTexture it = new ImageTexture(g,res);\r
93                                 org.simantics.image.stubs.Image pattern = it.getImage();\r
94                                 releaseImage(pattern.getResource());\r
95                                 t.setImage(null);\r
96                                 textureReferences.remove(res);\r
97                                 //FIXME : release the texture\r
98                         } else {\r
99                                 textureReferences.put(res, i);\r
100                         }\r
101                         \r
102                 } else {\r
103                         throw new RuntimeException("Cannot released texture that does not exist " + res);\r
104                 }\r
105         }\r
106         \r
107         public Image loadImage(Graph g, Resource res) {\r
108                 Image image = images.get(res);\r
109                 if (image == null) {\r
110                         org.simantics.image.stubs.Image pattern = new org.simantics.image.stubs.Image(g,res);\r
111                         IImageFactory f = org.simantics.proconf.image.ImageUtils.getImageFactoryForResource(g,pattern.getResource());\r
112                 try {\r
113                         IImage p = f.createImageForResource(g,pattern.getResource());\r
114                 PixelDimension pd = p.getDimensions().getPixelDimension();\r
115                 if (pd==null) pd = DEFAULT_SIZE;\r
116                         ImageData data = p.rasterize(pd.getWidth(), pd.getHeight());\r
117                         image = getImage(data);\r
118                         images.put(res, image);\r
119                         \r
120                 } catch (Exception e) {\r
121                         ErrorLogger.defaultLogError("Cannor create pattern texture for resource " + pattern, e);\r
122                         return null;\r
123                 }\r
124                 }\r
125                 addImageReference(res);\r
126                 return image;\r
127                 \r
128         }\r
129         \r
130         private void addTextureReference(Resource res) {\r
131                 Integer i = textureReferences.get(res);\r
132                 if (i != null) {\r
133                         imageReferences.put(res, i + 1);\r
134                 } else {\r
135                         imageReferences.put(res, 1);\r
136                 }\r
137         }\r
138         \r
139         private void addImageReference(Resource res) {\r
140                 Integer i = imageReferences.get(res);\r
141                 if (i != null) {\r
142                         imageReferences.put(res, i + 1);\r
143                 } else {\r
144                         imageReferences.put(res, 1);\r
145                 }\r
146         }\r
147         \r
148         public void releaseImage(Resource res) {\r
149                 Integer i = imageReferences.get(res);\r
150                 if (i != null) {\r
151                         i = i - 1;\r
152                         if (i == 0) {\r
153                                 Image image = images.get(res);\r
154                                 image.getData().clear();\r
155                                 image.setData(null);\r
156                                 images.remove(res);\r
157                                 imageReferences.remove(res);\r
158                         } else {\r
159                                 imageReferences.put(res, i);\r
160                         }\r
161                 } else {\r
162                         throw new RuntimeException("Cannot release image that does not exist.");\r
163                 }\r
164         }\r
165         \r
166         public static ResourceTextureCache getInstance() {\r
167                 return instance;\r
168         }\r
169         \r
170         private static Image getImage(ImageData imageData) {\r
171         int width = imageData.width;\r
172         int height = imageData.height;\r
173         int type = 0;\r
174         \r
175         int components = 3;\r
176         \r
177         type = Image.RGB888;\r
178         if (imageData.alphaData != null) {\r
179                 type = Image.RGBA8888;\r
180                 components = 4;\r
181         }\r
182         \r
183         ByteBuffer buf = ByteBuffer.allocateDirect(components * width * height);\r
184         ImageUtils.convertToRGBA(imageData, buf);       \r
185         return new Image(type,width,height,buf);\r
186     }\r
187         \r
188         \r
189         public static void setTextureCoordGenerator(TextureCoordinateGenerator gen, com.jme.image.Texture texture) {\r
190         if (gen == null)\r
191             return ;\r
192 \r
193         //g3dResource.\r
194         if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_sphere))\r
195                 texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_SPHERE);\r
196         else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_eyelinear))\r
197                 texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_EYE_LINEAR);\r
198         else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_objectlinear))\r
199                 texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_OBJECT_LINEAR);\r
200         else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_normal))\r
201                 ErrorLogger.getDefault().logWarning("JME doesn't support normal texture coordinate generation", null);\r
202         else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_reflection))\r
203                 ErrorLogger.getDefault().logWarning("JME doesn't support reflection texture coordinate generation", null);\r
204         else\r
205                 ErrorLogger.getDefault().logWarning("Unsupported TexGen type " + gen.getName(), null);\r
206     }\r
207         \r
208         public void clear() {\r
209                 for (Image i : images.values())\r
210                         i.setData(null);\r
211                 for (Texture t : textures.values())\r
212                         t.setImage(null);\r
213                 imageReferences.clear();\r
214                 textureReferences.clear();\r
215                 images.clear();\r
216                 textures.clear();\r
217         \r
218         }\r
219 \r
220 }\r