]> gerrit.simantics Code Review - simantics/3d.git/blob - org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java
f29ddb47da2cb5921dd4470b917b50b52bdbf740
[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.ui.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 \r
22 /**\r
23  * Caches resource based textures.\r
24  * TODO : use queries to update textures, now textures are read once and cannot be updated\r
25  * TODO : either use shared context or use separate cache for each editor\r
26  * TODO : ShapeNode implementation won't use release texture yet\r
27  * 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
28  * TODO : Support for other types of textures (not just pattern texture, preferably extensible interface)\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 \r
57                         if (image == null) {\r
58                                 return null;\r
59                         }\r
60                         t = new Texture();\r
61                         t.setImage(image);\r
62                         \r
63                 \r
64                         t.setFilter(com.jme.image.Texture.FM_LINEAR);\r
65                 t.setMipmapState(com.jme.image.Texture.MM_LINEAR);\r
66                 t.setApply(Texture.AM_COMBINE);\r
67                 t.setCombineFuncRGB(Texture.ACF_MODULATE);\r
68                 t.setCombineScaleRGB(2.f);\r
69 \r
70                 //t.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T);\r
71                         \r
72                         TextureCoordinateGenerator gen = it.getTextureCoordinateGenerator();\r
73                         setTextureCoordGenerator(gen, t);\r
74                         textures.put(res, t);\r
75                 }\r
76                 addTextureReference(res);\r
77                 return t;\r
78         }\r
79         \r
80         public void releaseTexture(Graph g, Resource res) {\r
81                 Integer i = textureReferences.get(res);\r
82                 if (i != null) {\r
83                         i = i - 1;\r
84                         if (i == 0) {\r
85                                 Texture t = textures.get(res);\r
86                                 ImageTexture it = new ImageTexture(g,res);\r
87                                 org.simantics.image.stubs.Image pattern = it.getImage();\r
88                                 releaseImage(pattern.getResource());\r
89                                 t.setImage(null);\r
90                                 textureReferences.remove(res);\r
91                                 //FIXME : release the texture\r
92                         } else {\r
93                                 textureReferences.put(res, i);\r
94                         }\r
95                         \r
96                 } else {\r
97                         throw new RuntimeException("Cannot released texture that does not exist " + res);\r
98                 }\r
99         }\r
100         \r
101         public Image loadImage(Graph g, Resource res) {\r
102                 Image image = images.get(res);\r
103                 if (image == null) {\r
104                         org.simantics.image.stubs.Image pattern = new org.simantics.image.stubs.Image(g,res);\r
105                         IImageFactory f = org.simantics.proconf.image.ImageUtils.getImageFactoryForResource(g,pattern.getResource());\r
106                 try {\r
107                         IImage p = f.createImageForResource(g,pattern.getResource());\r
108                 PixelDimension pd = p.getDimensions().getPixelDimension();\r
109                 if (pd==null) pd = DEFAULT_SIZE;\r
110                         ImageData data = p.rasterize(pd.getWidth(), pd.getHeight());\r
111                         image = getImage(data);\r
112                         images.put(res, image);\r
113                         \r
114                 } catch (Exception e) {\r
115                         ErrorLogger.defaultLogError("Cannor create pattern texture for resource " + pattern, e);\r
116                         return null;\r
117                 }\r
118                 }\r
119                 addImageReference(res);\r
120                 return image;\r
121                 \r
122         }\r
123         \r
124         private void addTextureReference(Resource res) {\r
125                 Integer i = textureReferences.get(res);\r
126                 if (i != null) {\r
127                         imageReferences.put(res, i + 1);\r
128                 } else {\r
129                         imageReferences.put(res, 1);\r
130                 }\r
131         }\r
132         \r
133         private void addImageReference(Resource res) {\r
134                 Integer i = imageReferences.get(res);\r
135                 if (i != null) {\r
136                         imageReferences.put(res, i + 1);\r
137                 } else {\r
138                         imageReferences.put(res, 1);\r
139                 }\r
140         }\r
141         \r
142         public void releaseImage(Resource res) {\r
143                 Integer i = imageReferences.get(res);\r
144                 if (i != null) {\r
145                         i = i - 1;\r
146                         if (i == 0) {\r
147                                 Image image = images.get(res);\r
148                                 image.getData().clear();\r
149                                 image.setData(null);\r
150                                 images.remove(res);\r
151                                 imageReferences.remove(res);\r
152                         } else {\r
153                                 imageReferences.put(res, i);\r
154                         }\r
155                 } else {\r
156                         throw new RuntimeException("Cannot release image that does not exist.");\r
157                 }\r
158         }\r
159         \r
160         public static ResourceTextureCache getInstance() {\r
161                 return instance;\r
162         }\r
163         \r
164         public static Image getImage(ImageData imageData) {\r
165         int width = imageData.width;\r
166         int height = imageData.height;\r
167         int type = 0;\r
168         \r
169         int components = 3;\r
170         \r
171         type = Image.RGB888;\r
172         if (imageData.alphaData != null) {\r
173                 type = Image.RGBA8888;\r
174                 components = 4;\r
175         }\r
176         \r
177         ByteBuffer buf = ByteBuffer.allocateDirect(components * width * height);\r
178         ImageUtils.convertToRGBA(imageData, buf);       \r
179         return new Image(type,width,height,buf);\r
180     }\r
181         \r
182         \r
183         public static void setTextureCoordGenerator(TextureCoordinateGenerator gen, com.jme.image.Texture texture) {\r
184         if (gen == null)\r
185             return ;\r
186 \r
187         //g3dResource.\r
188         if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_sphere))\r
189                 texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_SPHERE);\r
190         else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_eyelinear))\r
191                 texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_EYE_LINEAR);\r
192         else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_objectlinear))\r
193                 texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_OBJECT_LINEAR);\r
194         else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_normal))\r
195                 ErrorLogger.getDefault().logWarning("JME doesn't support normal texture coordinate generation", null);\r
196         else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_reflection))\r
197                 ErrorLogger.getDefault().logWarning("JME doesn't support reflection texture coordinate generation", null);\r
198         else\r
199                 ErrorLogger.getDefault().logWarning("Unsupported TexGen type " + gen.getName(), null);\r
200     }\r
201         \r
202         public void clear() {\r
203                 for (Image i : images.values())\r
204                         i.setData(null);\r
205                 for (Texture t : textures.values())\r
206                         t.setImage(null);\r
207                 imageReferences.clear();\r
208                 textureReferences.clear();\r
209                 images.clear();\r
210                 textures.clear();\r
211         \r
212         }\r
213 \r
214 }\r