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