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.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
21 import com.jme.util.TextureManager;
\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
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
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
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
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
76 //t.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T);
\r
78 TextureCoordinateGenerator gen = it.getTextureCoordinateGenerator();
\r
79 setTextureCoordGenerator(gen, t);
\r
80 textures.put(res, t);
\r
82 addTextureReference(res);
\r
86 public void releaseTexture(Graph g, Resource res) {
\r
87 Integer i = textureReferences.get(res);
\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
96 textureReferences.remove(res);
\r
97 //FIXME : release the texture
\r
99 textureReferences.put(res, i);
\r
103 throw new RuntimeException("Cannot released texture that does not exist " + res);
\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
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
120 } catch (Exception e) {
\r
121 ErrorLogger.defaultLogError("Cannor create pattern texture for resource " + pattern, e);
\r
125 addImageReference(res);
\r
130 private void addTextureReference(Resource res) {
\r
131 Integer i = textureReferences.get(res);
\r
133 imageReferences.put(res, i + 1);
\r
135 imageReferences.put(res, 1);
\r
139 private void addImageReference(Resource res) {
\r
140 Integer i = imageReferences.get(res);
\r
142 imageReferences.put(res, i + 1);
\r
144 imageReferences.put(res, 1);
\r
148 public void releaseImage(Resource res) {
\r
149 Integer i = imageReferences.get(res);
\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
159 imageReferences.put(res, i);
\r
162 throw new RuntimeException("Cannot release image that does not exist.");
\r
166 public static ResourceTextureCache getInstance() {
\r
170 private static Image getImage(ImageData imageData) {
\r
171 int width = imageData.width;
\r
172 int height = imageData.height;
\r
175 int components = 3;
\r
177 type = Image.RGB888;
\r
178 if (imageData.alphaData != null) {
\r
179 type = Image.RGBA8888;
\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
189 public static void setTextureCoordGenerator(TextureCoordinateGenerator gen, com.jme.image.Texture texture) {
\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
205 ErrorLogger.getDefault().logWarning("Unsupported TexGen type " + gen.getName(), null);
\r
208 public void clear() {
\r
209 for (Image i : images.values())
\r
211 for (Texture t : textures.values())
\r
213 imageReferences.clear();
\r
214 textureReferences.clear();
\r