/******************************************************************************* * Copyright (c) 2007 VTT Technical Research Centre of Finland and others. * 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.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.eclipse.swt.graphics.Device; import org.simantics.layer0.utils.IEntity; import org.simantics.layer0.utils.StubLinkedList; import org.simantics.proconf.g3d.Resources; import org.simantics.proconf.g3d.stubs.Appearance; import org.simantics.proconf.g3d.stubs.Color; import org.simantics.proconf.g3d.stubs.ImageTexture; import org.simantics.proconf.g3d.stubs.Material; import org.simantics.proconf.g3d.stubs.MultiTexture; import org.simantics.proconf.g3d.stubs.MultiTextureMode; import org.simantics.proconf.g3d.stubs.Shader; import org.simantics.proconf.g3d.stubs.Texture; import org.simantics.utils.ui.ErrorLogger; import com.jme.image.Image; import com.jme.renderer.ColorRGBA; import com.jme.renderer.Renderer; import com.jme.scene.Geometry; import com.jme.scene.state.AlphaState; import com.jme.scene.state.FragmentProgramState; import com.jme.scene.state.MaterialState; import com.jme.scene.state.RenderState; import com.jme.scene.state.TextureState; import com.jme.scene.state.VertexProgramState; public class AppearanceTools { public static void setColor(Color color, org.eclipse.swt.graphics.Color c) { color.setRed(new double[]{(double)c.getRed() / 255.0}); color.setGreen(new double[]{(double)c.getGreen() / 255.0}); color.setBlue(new double[]{(double)c.getBlue() / 255.0}); } public static org.eclipse.swt.graphics.Color getColor(Color color, Device device) { org.eclipse.swt.graphics.Color c = new org.eclipse.swt.graphics.Color(device, (int)(color.getRed()[0] * 255.0), (int)(color.getGreen()[0] * 255.0),(int)(color.getBlue()[0] * 255.0)); return c; } /** * Returns collection of renderstates that represent the given appearance. * Note : if collection contains an alphastate, node must be inserted to transparent rendering queue.! * @param appearance * @param renderer * @return */ public static Collection getAppearance(Appearance appearance, Renderer renderer) { Material m = appearance.getMaterial(); List states = new ArrayList(); if (m != null) { states.addAll(getMaterial(m, renderer)); } Texture t = appearance.getTexture(); if (t != null) { if (t.isInstanceOf(Resources.g3dResource.ImageTexture)) { states.addAll(getPatternTexture(t, renderer)); } else if (t.isInstanceOf(Resources.g3dResource.Texture3D)) { ErrorLogger.getDefault().logWarning("JME doesn't support volume textures!", null); } else if (t.isInstanceOf(Resources.g3dResource.MultiTexture)) { states.addAll(getMultiTexture(t, renderer)); } else if (t.isInstanceOf(Resources.g3dResource.CubeMapTexture)) { ErrorLogger.getDefault().logWarning("JME doesn't support cubemap textures!", null); } else { throw new UnsupportedOperationException("Unsupported texture"); } } Shader s = appearance.getShader(); if (s != null) { states.addAll(getShader(s, renderer)); } return states; } private static ColorRGBA getJMEColor(Color color) { return new ColorRGBA((float)color.getRed()[0],(float)color.getGreen()[0],(float)color.getBlue()[0],0.f); } private static ColorRGBA getJMEColor(Color color, float alpha) { return new ColorRGBA((float)color.getRed()[0],(float)color.getGreen()[0],(float)color.getBlue()[0],alpha); } private static Collection getMaterial(Material m , Renderer renderer) { float alpha = 0.f; MaterialState ms = renderer.createMaterialState(); List states = new ArrayList(); if (m.getTransparency()[0] > 0.0) { AlphaState as = renderer.createAlphaState(); as.setBlendEnabled(true); as.setSrcFunction(AlphaState.DB_SRC_ALPHA); as.setDstFunction(AlphaState.DB_ONE_MINUS_SRC_ALPHA); states.add(as); alpha = 1.f - (float)m.getTransparency()[0]; //node.setRenderQueueMode(Renderer.QUEUE_TRANSPARENT); ms.setMaterialFace(MaterialState.MF_FRONT_AND_BACK); } else { //node.setRenderQueueMode(Renderer.QUEUE_OPAQUE); } ms.setEmissive(getJMEColor(m.getEmissiveColor())); ms.setSpecular(getJMEColor(m.getSpecularColor())); ms.setAmbient(getJMEColor(m.getAmbientColor())); ms.setDiffuse(getJMEColor(m.getDiffuseColor(),alpha)); ms.setShininess((float) m.getShininess()[0]); //node.setRenderState(ms); states.add(ms); return states; } private static Collection getShader(Shader s , Renderer renderer) { List states = new ArrayList(); VertexProgramState vs = renderer.createVertexProgramState(); vs.load(s.getVertexShader()[0]); FragmentProgramState fs = renderer.createFragmentProgramState(); fs.load(s.getFragmentShader()[0]); states.add(vs); states.add(fs); return states; } private static Collection getPatternTexture(Texture t, Renderer renderer) { List states = new ArrayList(); com.jme.image.Texture texture = ResourceTextureCache.getInstance().loadTexture(t.getGraph(), t.getResource()); if (texture == null) return states; TextureState state = renderer.createTextureState(); state.setTexture(texture); state.setEnabled(true); states.add(state); return states; } private static Image getPatternTexture(ImageTexture t) { return ResourceTextureCache.getInstance().loadImage(t.getGraph(), t.getResource()); } private static Collection getMultiTexture(Texture t, Renderer renderer) { List states = new ArrayList(); TextureState state = renderer.createTextureState(); MultiTexture t3 = new MultiTexture(t); Collection mtList = t3.getRelatedObjects(Resources.g3dResource.HasMultiTextureElementList); assert (mtList.size() == 1); //this is required in the ontology! StubLinkedList list = new StubLinkedList(mtList.iterator().next()); for (int i = 0; i < list.size(); i++) { IEntity ie = list.get(i); //MultiTextureElement e = new MultiTextureElement(ie); Texture tex = new Texture(ie); //e.getTexture(); MultiTextureMode mode = tex.getTextureMode();//e.getTextureMode(); com.jme.image.Texture texture = new com.jme.image.Texture(); texture.setFilter(com.jme.image.Texture.FM_LINEAR); texture.setMipmapState(com.jme.image.Texture.MM_LINEAR_LINEAR); texture.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T); if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_add)) { texture.setApply(com.jme.image.Texture.AM_ADD); } else if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_modulate)) { texture.setApply(com.jme.image.Texture.AM_MODULATE); } else if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_decal)) { texture.setApply(com.jme.image.Texture.AM_DECAL); } else if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_blend)) { texture.setApply(com.jme.image.Texture.AM_BLEND); } else if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_replace)) { texture.setApply(com.jme.image.Texture.AM_REPLACE); } else if (mode.getResource().equals(Resources.g3dResource.MultiTextureMode_combine)) { texture.setApply(com.jme.image.Texture.AM_COMBINE); //CombineMode cm = e.getCombineMode(); //CombineSource cs = e.getCombineSource(); StubLinkedList combine = new StubLinkedList(tex.getCombineDefinition()); setCombineAttributes(texture, combine); //att.setBlendColor(blendColor) //att.setTexBlendColor(texBlendColor) //att.setTextureBlendColor(color) //att.setTextureTransform(transform) } else { throw new UnsupportedOperationException("Texture mode not supported"); } if (tex.isInstanceOf(Resources.g3dResource.MultiTexture)) { ErrorLogger.defaultLogError("MultiTexture contains another MultiTexture which is not allowed", null); continue; } else if (tex.isInstanceOf(Resources.g3dResource.ImageTexture)) { Image image = getPatternTexture(new ImageTexture(tex)); if (image != null) texture.setImage(image); } else if (tex.isInstanceOf(Resources.g3dResource.Texture3D)) { ErrorLogger.getDefault().logWarning("JME doesn't support volume textures!", null); } else if (tex.isInstanceOf(Resources.g3dResource.CubeMapTexture)) { ErrorLogger.getDefault().logWarning("JME doesn't support cubemap textures!", null); } else { throw new UnsupportedOperationException("Unsupported texture"); } state.setTexture(texture, i); } states.add(state); return states; //MultiTextureElementList texturesList = t3.getMultiTextureElementList(); //List textures = texturesList.toStandAloneList(); //ArrayList states = new ArrayList(); // for (MultiTextureElement e : textures) { // Texture tex = e.getTexture(); //int index = e.getMultiTextureIndexValue(); //String mode = e.getMultiTextureModeValue(); // com.jme.image.Texture texture = new com.jme.image.Texture(); // texture.setFilter(com.jme.image.Texture.FM_LINEAR); // texture.setMipmapState(com.jme.image.Texture.MM_LINEAR_LINEAR); // texture.setWrap(com.jme.image.Texture.WM_WRAP_S_WRAP_T); // if (mode.startsWith(TEXTURE_MODE_MODULATE)) { // texture.setApply(com.jme.image.Texture.AM_MODULATE); // } else if (mode.startsWith(TEXTURE_MODE_DECAL)) { // texture.setCombineFuncRGB(com.jme.image.Texture.AM_DECAL); // } else if (mode.startsWith(TEXTURE_MODE_BLEND)) { // texture.setCombineFuncRGB(com.jme.image.Texture.AM_MODULATE); // } else if (mode.startsWith(TEXTURE_MODE_REPLACE)) { // texture.setCombineFuncRGB(com.jme.image.Texture.AM_REPLACE); // } else if (mode.startsWith(TEXTURE_MODE_COMBINE)) { // texture.setCombineFuncRGB(com.jme.image.Texture.AM_COMBINE); // // mode = mode.substring(TEXTURE_MODE_COMBINE.length()+1); // setCombineAttributes(texture, mode); //att.setBlendColor(blendColor) //att.setTexBlendColor(texBlendColor) //att.setTextureBlendColor(color) //att.setTextureTransform(transform) // } else { // throw new UnsupportedOperationException("Texture mode not supported"); // } // // // if (tex.isInstanceOf(Resources.g3dResource.MultiTexture)) { // ErrorLogger.defaultLogError("MultiTexture contains another MultiTexture which is not allowed", null); // continue; // } else if (tex.isInstanceOf(Resources.g3dResource.ImageTexture)) { // Image image = getPatternTexture(ImageTextureFactory.create(tex)); // if (image != null) // texture.setImage(image); // // } else if (tex.isInstanceOf(Resources.g3dResource.Texture3D)) { // ErrorLogger.getDefault().logWarning("JME doesn't support volume textures!", null); // // } else if (tex.isInstanceOf(Resources.g3dResource.CubeMapTexture)) { // ErrorLogger.getDefault().logWarning("JME doesn't support cubemap textures!", null); // // } else { // throw new UnsupportedOperationException("Unsupported texture"); // } //FIXME ! //state.setTexture(texture, index); // } // node.setRenderState(state); } private static void setCombineAttributes(com.jme.image.Texture texture, StubLinkedList definition) { // TODO : rgb and alpha scale Iterator it = definition.iterator(); IEntity mode = it.next(); if (mode.getResource().equals(Resources.g3dResource.CombineMode_add)) { texture.setCombineFuncRGB(com.jme.image.Texture.ACF_ADD); } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_addsigned)) { texture.setCombineFuncRGB(com.jme.image.Texture.ACF_ADD_SIGNED); } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_dot3)) { texture.setCombineFuncRGB(com.jme.image.Texture.ACF_DOT3_RGB); } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_interpolate)) { texture.setCombineFuncRGB(com.jme.image.Texture.ACF_INTERPOLATE); } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_modulate)) { texture.setCombineFuncRGB(com.jme.image.Texture.ACF_MODULATE); } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_replace)) { texture.setCombineFuncRGB(com.jme.image.Texture.ACF_REPLACE); } else if (mode.getResource().equals(Resources.g3dResource.CombineMode_subtract)) { texture.setCombineFuncRGB(com.jme.image.Texture.ACF_SUBTRACT); } else { throw new UnsupportedOperationException("Unsupported combine mode"); } mode = it.next(); int i = 0; for (i = 0; i < 3; i++) { int m; if (mode.getResource().equals(Resources.g3dResource.CombineSource_constantcolor)) { m = com.jme.image.Texture.ACS_CONSTANT; } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_objectcolor)) { m = com.jme.image.Texture.ACS_PRIMARY_COLOR; } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_previousstate)) { m = com.jme.image.Texture.ACS_TEXTURE; } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texturecolor)) { m = com.jme.image.Texture.ACS_TEXTURE; } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texture0)) { m = com.jme.image.Texture.ACS_TEXTURE; } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texture1)) { m = com.jme.image.Texture.ACS_TEXTURE; } else { break; //throw new UnsupportedOperationException("Texture combine source not supported"); } mode = it.next(); switch (i) { case 0: texture.setCombineSrc0RGB(m); break; case 1: texture.setCombineSrc1RGB(m); break; case 2: texture.setCombineSrc2RGB(m); break; } } if (i > 0) { for (i = 0; i < 3; i++) { int m; if (mode.getResource().equals(Resources.g3dResource.CombineFunction_srccolor)) { m = com.jme.image.Texture.ACO_SRC_COLOR; } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_srcalpha)) { m = com.jme.image.Texture.ACO_SRC_ALPHA; } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_oneminussrccolor)) { m = com.jme.image.Texture.ACO_ONE_MINUS_SRC_COLOR; } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_oneminussrcalpha)) { m = com.jme.image.Texture.ACO_ONE_MINUS_SRC_ALPHA; } else { break; } mode = it.next(); switch (i) { case 0: texture.setCombineOp0RGB(m); break; case 1: texture.setCombineOp1RGB(m); break; case 2: texture.setCombineOp2RGB(m); break; } } } for (i = 0; i < 3; i++) { int m; if (mode.getResource().equals(Resources.g3dResource.CombineSource_constantcolor)) { m = com.jme.image.Texture.ACS_CONSTANT; } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_objectcolor)) { m = com.jme.image.Texture.ACS_PRIMARY_COLOR; } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_previousstate)) { m = com.jme.image.Texture.ACS_TEXTURE; } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texturecolor)) { m = com.jme.image.Texture.ACS_TEXTURE; } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texture0)) { m = com.jme.image.Texture.ACS_TEXTURE; } else if (mode.getResource().equals(Resources.g3dResource.CombineSource_texture1)) { m = com.jme.image.Texture.ACS_TEXTURE; } else { break; //throw new UnsupportedOperationException("Texture combine source not supported"); } mode = it.next(); switch (i) { case 0: texture.setCombineSrc0Alpha(m); break; case 1: texture.setCombineSrc1Alpha(m); break; case 2: texture.setCombineSrc2Alpha(m); break; } } if (i > 0) { for (i = 0; i < 3; i++) { int m; if (mode.getResource().equals(Resources.g3dResource.CombineFunction_srccolor)) { m = com.jme.image.Texture.ACO_SRC_COLOR; } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_srcalpha)) { m = com.jme.image.Texture.ACO_SRC_ALPHA; } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_oneminussrccolor)) { m = com.jme.image.Texture.ACO_ONE_MINUS_SRC_COLOR; } else if (mode.getResource().equals(Resources.g3dResource.CombineFunction_oneminussrcalpha)) { m = com.jme.image.Texture.ACO_ONE_MINUS_SRC_ALPHA; } else { break; } mode = it.next(); switch (i) { case 0: texture.setCombineOp0Alpha(m); break; case 1: texture.setCombineOp1Alpha(m); break; case 2: texture.setCombineOp2Alpha(m); break; } } } } public static void copyMaterial(Geometry from, Geometry to) { for (int i = RenderState.RS_ALPHA; i < RenderState.RS_MAX_STATE; i++) { RenderState rs = from.getRenderState(i); if (rs != null) to.setRenderState(rs); } } }