1 package org.simantics.proconf.g3d.base;
\r
3 import java.nio.ByteBuffer;
\r
4 import java.util.HashMap;
\r
5 import java.util.Map;
\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
19 import com.jme.image.Image;
\r
20 import com.jme.image.Texture;
\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
30 * @author Marko Luukkainen <Marko.Luukkainen@vtt.fi>
\r
33 public class ResourceTextureCache {
\r
35 public static PixelDimension DEFAULT_SIZE = new PixelDimension(128,128);
\r
37 private static ResourceTextureCache instance = new ResourceTextureCache();
\r
39 private Map<Resource,Image> images = new HashMap<Resource, Image>();
\r
40 private Map<Resource,Integer> imageReferences = new HashMap<Resource, Integer>();
\r
42 private Map<Resource,Texture> textures = new HashMap<Resource, Texture>();
\r
43 private Map<Resource,Integer> textureReferences = new HashMap<Resource, Integer>();
\r
46 private ResourceTextureCache() {
\r
50 public Texture loadTexture(Graph g, Resource res) {
\r
51 Texture t = textures.get(res);
\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
57 if (image == null) {
\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
70 //t.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T);
\r
72 TextureCoordinateGenerator gen = it.getTextureCoordinateGenerator();
\r
73 setTextureCoordGenerator(gen, t);
\r
74 textures.put(res, t);
\r
76 addTextureReference(res);
\r
80 public void releaseTexture(Graph g, Resource res) {
\r
81 Integer i = textureReferences.get(res);
\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
90 textureReferences.remove(res);
\r
91 //FIXME : release the texture
\r
93 textureReferences.put(res, i);
\r
97 throw new RuntimeException("Cannot released texture that does not exist " + res);
\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
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
114 } catch (Exception e) {
\r
115 ErrorLogger.defaultLogError("Cannor create pattern texture for resource " + pattern, e);
\r
119 addImageReference(res);
\r
124 private void addTextureReference(Resource res) {
\r
125 Integer i = textureReferences.get(res);
\r
127 imageReferences.put(res, i + 1);
\r
129 imageReferences.put(res, 1);
\r
133 private void addImageReference(Resource res) {
\r
134 Integer i = imageReferences.get(res);
\r
136 imageReferences.put(res, i + 1);
\r
138 imageReferences.put(res, 1);
\r
142 public void releaseImage(Resource res) {
\r
143 Integer i = imageReferences.get(res);
\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
153 imageReferences.put(res, i);
\r
156 throw new RuntimeException("Cannot release image that does not exist.");
\r
160 public static ResourceTextureCache getInstance() {
\r
164 public static Image getImage(ImageData imageData) {
\r
165 int width = imageData.width;
\r
166 int height = imageData.height;
\r
169 int components = 3;
\r
171 type = Image.RGB888;
\r
172 if (imageData.alphaData != null) {
\r
173 type = Image.RGBA8888;
\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
183 public static void setTextureCoordGenerator(TextureCoordinateGenerator gen, com.jme.image.Texture texture) {
\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
199 ErrorLogger.getDefault().logWarning("Unsupported TexGen type " + gen.getName(), null);
\r
202 public void clear() {
\r
203 for (Image i : images.values())
\r
205 for (Texture t : textures.values())
\r
207 imageReferences.clear();
\r
208 textureReferences.clear();
\r