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
9 * VTT Technical Research Centre of Finland - initial API and implementation
\r
10 *******************************************************************************/
\r
11 package org.simantics.proconf.g3d.base;
\r
13 import java.nio.ByteBuffer;
\r
14 import java.util.HashMap;
\r
15 import java.util.Map;
\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
29 import com.jme.image.Image;
\r
30 import com.jme.image.Texture;
\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
40 * @author Marko Luukkainen <Marko.Luukkainen@vtt.fi>
\r
43 public class ResourceTextureCache {
\r
45 public static PixelDimension DEFAULT_SIZE = new PixelDimension(128,128);
\r
47 private static ResourceTextureCache instance = new ResourceTextureCache();
\r
49 private Map<Resource,Image> images = new HashMap<Resource, Image>();
\r
50 private Map<Resource,Integer> imageReferences = new HashMap<Resource, Integer>();
\r
52 private Map<Resource,Texture> textures = new HashMap<Resource, Texture>();
\r
53 private Map<Resource,Integer> textureReferences = new HashMap<Resource, Integer>();
\r
56 private ResourceTextureCache() {
\r
60 public Texture loadTexture(Graph g, Resource res) {
\r
61 Texture t = textures.get(res);
\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
67 if (image == null) {
\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
80 //t.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T);
\r
82 TextureCoordinateGenerator gen = it.getTextureCoordinateGenerator();
\r
83 setTextureCoordGenerator(gen, t);
\r
84 textures.put(res, t);
\r
86 addTextureReference(res);
\r
90 public void releaseTexture(Graph g, Resource res) {
\r
91 Integer i = textureReferences.get(res);
\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
100 textureReferences.remove(res);
\r
101 //FIXME : release the texture
\r
103 textureReferences.put(res, i);
\r
107 throw new RuntimeException("Cannot released texture that does not exist " + res);
\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
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
124 } catch (Exception e) {
\r
125 ErrorLogger.defaultLogError("Cannor create pattern texture for resource " + pattern, e);
\r
129 addImageReference(res);
\r
134 private void addTextureReference(Resource res) {
\r
135 Integer i = textureReferences.get(res);
\r
137 imageReferences.put(res, i + 1);
\r
139 imageReferences.put(res, 1);
\r
143 private void addImageReference(Resource res) {
\r
144 Integer i = imageReferences.get(res);
\r
146 imageReferences.put(res, i + 1);
\r
148 imageReferences.put(res, 1);
\r
152 public void releaseImage(Resource res) {
\r
153 Integer i = imageReferences.get(res);
\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
163 imageReferences.put(res, i);
\r
166 throw new RuntimeException("Cannot release image that does not exist.");
\r
170 public static ResourceTextureCache getInstance() {
\r
174 public static Image getImage(ImageData imageData) {
\r
175 int width = imageData.width;
\r
176 int height = imageData.height;
\r
179 int components = 3;
\r
181 type = Image.RGB888;
\r
182 if (imageData.alphaData != null) {
\r
183 type = Image.RGBA8888;
\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
193 public static void setTextureCoordGenerator(TextureCoordinateGenerator gen, com.jme.image.Texture texture) {
\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
209 ErrorLogger.getDefault().logWarning("Unsupported TexGen type " + gen.getName(), null);
\r
212 public void clear() {
\r
213 for (Image i : images.values())
\r
215 for (Texture t : textures.values())
\r
217 imageReferences.clear();
\r
218 textureReferences.clear();
\r