X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.g3d%2Fsrc%2Forg%2Fsimantics%2Fproconf%2Fg3d%2Fbase%2FResourceTextureCache.java;fp=org.simantics.g3d%2Fsrc%2Forg%2Fsimantics%2Fproconf%2Fg3d%2Fbase%2FResourceTextureCache.java;h=10ff6ce9b2fb03798d56b26a50c89c1a12084d19;hb=10f144a2bb2d7bec98b812b83acecb333fd098ea;hp=0000000000000000000000000000000000000000;hpb=3055b543aa5afc0cca4bb3b341704e7c5103fa6a;p=simantics%2F3d.git diff --git a/org.simantics.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java b/org.simantics.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java new file mode 100644 index 00000000..10ff6ce9 --- /dev/null +++ b/org.simantics.g3d/src/org/simantics/proconf/g3d/base/ResourceTextureCache.java @@ -0,0 +1,224 @@ +/******************************************************************************* + * Copyright (c) 2007- VTT Technical Research Centre of Finland. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.proconf.g3d.base; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; + +import org.eclipse.swt.graphics.ImageData; +import org.simantics.db.Graph; +import org.simantics.db.Resource; +import org.simantics.proconf.g3d.Resources; +import org.simantics.proconf.g3d.stubs.ImageTexture; +import org.simantics.proconf.g3d.stubs.TextureCoordinateGenerator; +import org.simantics.proconf.image.interfaces.IImage; +import org.simantics.proconf.image.interfaces.IImageFactory; +import org.simantics.utils.ui.ErrorLogger; +import org.simantics.utils.ui.gfx.ImageUtils; +import org.simantics.utils.ui.gfx.PixelDimension; + +import com.jme.image.Image; +import com.jme.image.Texture; + +/** + * Caches resource based textures. + * TODO : use queries to update textures, now textures are read once and cannot be updated + * TODO : either use shared context or use separate cache for each editor + * TODO : ShapeNode implementation won't use release texture yet + * 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. + * TODO : Support for other types of textures (not just pattern texture, preferably extensible interface) + * + * @author Marko Luukkainen + * + */ +public class ResourceTextureCache { + + public static PixelDimension DEFAULT_SIZE = new PixelDimension(128,128); + + private static ResourceTextureCache instance = new ResourceTextureCache(); + + private Map images = new HashMap(); + private Map imageReferences = new HashMap(); + + private Map textures = new HashMap(); + private Map textureReferences = new HashMap(); + + + private ResourceTextureCache() { + + } + + public Texture loadTexture(Graph g, Resource res) { + Texture t = textures.get(res); + if (t == null) { + ImageTexture it = new ImageTexture(g,res); + org.simantics.image.stubs.Image pattern = it.getImage(); + Image image = loadImage(g, pattern.getResource()); + + if (image == null) { + return null; + } + t = new Texture(); + t.setImage(image); + + + t.setFilter(com.jme.image.Texture.FM_LINEAR); + t.setMipmapState(com.jme.image.Texture.MM_LINEAR); + t.setApply(Texture.AM_COMBINE); + t.setCombineFuncRGB(Texture.ACF_MODULATE); + t.setCombineScaleRGB(2.f); + + //t.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T); + + TextureCoordinateGenerator gen = it.getTextureCoordinateGenerator(); + setTextureCoordGenerator(gen, t); + textures.put(res, t); + } + addTextureReference(res); + return t; + } + + public void releaseTexture(Graph g, Resource res) { + Integer i = textureReferences.get(res); + if (i != null) { + i = i - 1; + if (i == 0) { + Texture t = textures.get(res); + ImageTexture it = new ImageTexture(g,res); + org.simantics.image.stubs.Image pattern = it.getImage(); + releaseImage(pattern.getResource()); + t.setImage(null); + textureReferences.remove(res); + //FIXME : release the texture + } else { + textureReferences.put(res, i); + } + + } else { + throw new RuntimeException("Cannot released texture that does not exist " + res); + } + } + + public Image loadImage(Graph g, Resource res) { + Image image = images.get(res); + if (image == null) { + org.simantics.image.stubs.Image pattern = new org.simantics.image.stubs.Image(g,res); + IImageFactory f = org.simantics.proconf.image.ImageUtils.getImageFactoryForResource(g,pattern.getResource()); + try { + IImage p = f.createImageForResource(g,pattern.getResource()); + PixelDimension pd = p.getDimensions().getPixelDimension(); + if (pd==null) pd = DEFAULT_SIZE; + ImageData data = p.rasterize(pd.getWidth(), pd.getHeight()); + image = getImage(data); + images.put(res, image); + + } catch (Exception e) { + ErrorLogger.defaultLogError("Cannor create pattern texture for resource " + pattern, e); + return null; + } + } + addImageReference(res); + return image; + + } + + private void addTextureReference(Resource res) { + Integer i = textureReferences.get(res); + if (i != null) { + imageReferences.put(res, i + 1); + } else { + imageReferences.put(res, 1); + } + } + + private void addImageReference(Resource res) { + Integer i = imageReferences.get(res); + if (i != null) { + imageReferences.put(res, i + 1); + } else { + imageReferences.put(res, 1); + } + } + + public void releaseImage(Resource res) { + Integer i = imageReferences.get(res); + if (i != null) { + i = i - 1; + if (i == 0) { + Image image = images.get(res); + image.getData().clear(); + image.setData(null); + images.remove(res); + imageReferences.remove(res); + } else { + imageReferences.put(res, i); + } + } else { + throw new RuntimeException("Cannot release image that does not exist."); + } + } + + public static ResourceTextureCache getInstance() { + return instance; + } + + public static Image getImage(ImageData imageData) { + int width = imageData.width; + int height = imageData.height; + int type = 0; + + int components = 3; + + type = Image.RGB888; + if (imageData.alphaData != null) { + type = Image.RGBA8888; + components = 4; + } + + ByteBuffer buf = ByteBuffer.allocateDirect(components * width * height); + ImageUtils.convertToRGBA(imageData, buf); + return new Image(type,width,height,buf); + } + + + public static void setTextureCoordGenerator(TextureCoordinateGenerator gen, com.jme.image.Texture texture) { + if (gen == null) + return ; + + //g3dResource. + if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_sphere)) + texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_SPHERE); + else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_eyelinear)) + texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_EYE_LINEAR); + else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_objectlinear)) + texture.setEnvironmentalMapMode(com.jme.image.Texture.EM_OBJECT_LINEAR); + else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_normal)) + ErrorLogger.getDefault().logWarning("JME doesn't support normal texture coordinate generation", null); + else if (gen.equals(Resources.g3dResource.TextureCoordinateGenerator_reflection)) + ErrorLogger.getDefault().logWarning("JME doesn't support reflection texture coordinate generation", null); + else + ErrorLogger.getDefault().logWarning("Unsupported TexGen type " + gen.getName(), null); + } + + public void clear() { + for (Image i : images.values()) + i.setData(null); + for (Texture t : textures.values()) + t.setImage(null); + imageReferences.clear(); + textureReferences.clear(); + images.clear(); + textures.clear(); + + } + +}