| /******************************************************************************* |
| * Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency |
| * 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: |
| * Pierre Allard, |
| * Regent L'Archeveque, |
| <<<<<<< HEAD |
| * Sebastien Gemme |
| * |
| ======= |
| * Sebastien Gemme - initial API and implementation |
| * |
| >>>>>>> refs/heads/eclipse_pa |
| * SPDX-License-Identifier: EPL-1.0 |
| * |
| *******************************************************************************/ |
| package org.eclipse.apogy.common.topology.ui.jme3; |
| |
| import java.awt.Color; |
| import java.awt.image.BufferedImage; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import javax.vecmath.Matrix3d; |
| import javax.vecmath.Vector3d; |
| |
| import org.eclipse.apogy.common.topology.ui.ShadowMode; |
| import org.eclipse.swt.graphics.RGB; |
| |
| import com.jme3.asset.AssetManager; |
| import com.jme3.material.Material; |
| import com.jme3.math.ColorRGBA; |
| import com.jme3.math.Matrix3f; |
| import com.jme3.math.Quaternion; |
| import com.jme3.math.Transform; |
| import com.jme3.math.Vector2f; |
| import com.jme3.math.Vector3f; |
| import com.jme3.scene.Geometry; |
| import com.jme3.scene.Mesh; |
| import com.jme3.scene.Node; |
| import com.jme3.scene.Spatial; |
| import com.jme3.scene.VertexBuffer; |
| import com.jme3.texture.Texture2D; |
| import com.jme3.texture.plugins.AWTLoader; |
| import com.jme3.util.BufferUtils; |
| |
| public class JME3Utilities { |
| private static OS os = OS.UNINITIALIZED; |
| |
| public enum OS { |
| UNINITIALIZED, LINUX, WINDOWS, MACOS |
| } |
| |
| public static ColorRGBA convertToColorRGBA(RGB rgb) { |
| if (rgb != null) { |
| return new ColorRGBA(rgb.red / 255.0f, rgb.green / 255.0f, rgb.blue / 255.0f, 1.0f); |
| } else { |
| return new ColorRGBA(1.0f, 1.0f, 1.0f, 0.0f); |
| |
| } |
| |
| } |
| |
| public static RGB convertToColorRGB(ColorRGBA colorRGBA) { |
| int red = Math.round(colorRGBA.r * 255.0f); |
| int green = Math.round(colorRGBA.g * 255.0f); |
| int blue = Math.round(colorRGBA.b * 255.0f); |
| return new RGB(red, green, blue); |
| } |
| |
| public static ColorRGBA convertToColorRGBA(javax.vecmath.Color3f color3f) { |
| return new ColorRGBA(color3f.x, color3f.y, color3f.z, 1.0f); |
| } |
| |
| public static java.awt.Color convertToAWTColor(ColorRGBA colorRGBA) { |
| return new Color(colorRGBA.getRed(), colorRGBA.getGreen(), colorRGBA.getBlue(), colorRGBA.getAlpha()); |
| } |
| |
| public static int[] convertToColorIntRGBA(ColorRGBA colorRGBA) { |
| int red = (int) Math.floor(colorRGBA.getRed() * 255.0); |
| int green = (int) Math.floor(colorRGBA.getGreen() * 255.0); |
| int blue = (int) Math.floor(colorRGBA.getBlue() * 255.0); |
| int alpha = (int) Math.floor(colorRGBA.getAlpha() * 255.0); |
| return new int[] { red, green, blue, alpha }; |
| } |
| |
| /** |
| * Creates a Geometry containing a reference frame |
| * |
| * @param axisLength |
| * @return |
| */ |
| public static Geometry createAxis3D(float axisLength, AssetManager assetManager) { |
| // Vertices |
| Vector3f[] vertices = new Vector3f[6]; |
| vertices[0] = new Vector3f(0, 0, 0); |
| vertices[1] = new Vector3f(axisLength, 0, 0); |
| |
| vertices[2] = new Vector3f(0, 0, 0); |
| vertices[3] = new Vector3f(0, axisLength, 0); |
| |
| vertices[4] = new Vector3f(0, 0, 0); |
| vertices[5] = new Vector3f(0, 0, axisLength); |
| |
| // Lines Index |
| int[] indexes = new int[] { 0, 1, 2, 3, 4, 5 }; |
| |
| // Colors |
| float[] colorArray = new float[] { 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1 }; |
| |
| // Creates a mesh shown as lines. |
| Mesh m = new Mesh(); |
| m.setMode(Mesh.Mode.Lines); |
| |
| m.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(vertices)); |
| m.setBuffer(VertexBuffer.Type.Index, 2, BufferUtils.createIntBuffer(indexes)); |
| m.setBuffer(com.jme3.scene.VertexBuffer.Type.Color, 4, colorArray); |
| m.updateBound(); |
| |
| Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
| mat.setBoolean("VertexColor", true); |
| Geometry geometry = new Geometry("Axis3D", m); |
| geometry.setMaterial(mat); |
| |
| return geometry; |
| } |
| |
| public static List<Geometry> getAllChildrenGeometry(Node node) { |
| List<Geometry> geometries = new ArrayList<Geometry>(); |
| |
| for (Spatial child : node.getChildren()) { |
| if (child instanceof Geometry) { |
| Geometry geometry = (Geometry) child; |
| geometries.add(geometry); |
| } else if (child instanceof Node) { |
| Node childNode = (Node) child; |
| geometries.addAll(getAllChildrenGeometry(childNode)); |
| } |
| } |
| |
| return geometries; |
| } |
| |
| public static Matrix3f convertToJME3Matrix3f(javax.vecmath.Matrix3d matrix3d) { |
| return new Matrix3f((float) matrix3d.m00, (float) matrix3d.m01, (float) matrix3d.m02, (float) matrix3d.m10, |
| (float) matrix3d.m11, (float) matrix3d.m12, (float) matrix3d.m20, (float) matrix3d.m21, |
| (float) matrix3d.m22); |
| } |
| |
| public static Quaternion createQuaternion(javax.vecmath.Matrix3d matrix3d) { |
| Matrix3f m = convertToJME3Matrix3f(matrix3d); |
| Quaternion quaternion = new Quaternion(); |
| quaternion.fromRotationMatrix(m); |
| |
| return quaternion; |
| } |
| |
| /** |
| * Creates a Transform based on a Matrix4d |
| * |
| * @param matrix4d The matrix4d. |
| * @return The resulting Transform. |
| */ |
| public static Transform createTransform(javax.vecmath.Matrix4d matrix4d) { |
| // Translation. |
| Vector3d position = new Vector3d(); |
| matrix4d.get(position); |
| Vector3f translation = new Vector3f((float) position.x, (float) position.y, (float) position.z); |
| |
| // Rotation. |
| javax.vecmath.Matrix3d matrix3d = new Matrix3d(); |
| matrix3d.setIdentity(); |
| matrix4d.get(matrix3d); |
| Quaternion rotation = JME3Utilities.createQuaternion(matrix3d); |
| |
| // Creates transform. |
| return new Transform(translation, rotation); |
| } |
| |
| /** |
| * Compute the normal associated with a triangle defined by three vertices in |
| * counter-clockwise direction. |
| * |
| * @param p0 The first vertex. |
| * @param p1 The second vertex. |
| * @param p2 The third vertex. |
| * @return The normal. |
| */ |
| public static Vector3f computeTriangleNormal(Vector3f p0, Vector3f p1, Vector3f p2) { |
| Vector3f v1 = new Vector3f(p1); |
| v1 = v1.subtract(p0); |
| |
| Vector3f v2 = new Vector3f(p2); |
| v2 = v2.subtract(p1); |
| Vector3f normal = v1.cross(v2); |
| |
| normal.normalize(); |
| return normal; |
| } |
| |
| public static float[] convertToFloatArray(Vector2f[][] input) { |
| int rows = input.length; |
| int columns = input[0].length; |
| |
| float[] array = new float[rows * columns * 2]; |
| int i = 0; |
| |
| for (int x = 0; x < rows; x++) { |
| for (int y = 0; y < columns; y++) { |
| Vector2f v = input[x][y]; |
| array[2 * i] = v.x; |
| array[2 * i + 1] = v.y; |
| i++; |
| } |
| } |
| |
| return array; |
| } |
| |
| /** |
| * Converts a List of Vector3f to an array of float. |
| * |
| * @param list The list. |
| * @return The array of float. |
| */ |
| public static float[] convertListOfVector2fToFloatArray(List<Vector2f> list) { |
| float[] array = new float[list.size() * 2]; |
| |
| int i = 0; |
| for (Vector2f v : list) { |
| array[2 * i] = v.x; |
| array[2 * i + 1] = v.y; |
| i++; |
| } |
| |
| return array; |
| } |
| |
| /** |
| * Converts a List of Vector3f to an array of float. |
| * |
| * @param list The list. |
| * @return The array of float. |
| */ |
| public static float[] convertToFloatArray(List<Vector3f> list) { |
| float[] array = new float[list.size() * 3]; |
| |
| int i = 0; |
| for (Vector3f v : list) { |
| array[3 * i] = v.x; |
| array[3 * i + 1] = v.y; |
| array[3 * i + 2] = v.z; |
| i++; |
| } |
| |
| return array; |
| } |
| |
| /** |
| * Converts a List of Vector3f to an array of float. |
| * |
| * @param list The list. |
| * @return The array of float. |
| */ |
| public static float[] convertVector2fListToFloatArray(List<Vector2f> list) { |
| float[] array = new float[list.size() * 2]; |
| |
| int i = 0; |
| for (Vector2f v : list) { |
| array[2 * i] = v.x; |
| array[2 * i + 1] = v.y; |
| i++; |
| } |
| |
| return array; |
| } |
| |
| /** |
| * Converts a List of Integer to an array of int. |
| * |
| * @param list The list. |
| * @return The array of int. |
| */ |
| public static int[] convertToIntArray(List<Integer> list) { |
| int[] array = new int[list.size()]; |
| int i = 0; |
| for (Integer value : list) { |
| array[i] = value.intValue(); |
| i++; |
| } |
| return array; |
| } |
| |
| public static float[] convertRGBAListToFloatArray(List<ColorRGBA> list) { |
| float[] array = new float[list.size() * 4]; |
| |
| int i = 0; |
| for (ColorRGBA color : list) { |
| int indexBase = 4 * i; |
| array[indexBase] = color.r; |
| array[indexBase + 1] = color.g; |
| array[indexBase + 2] = color.b; |
| array[indexBase + 3] = color.a; |
| i++; |
| } |
| |
| return array; |
| } |
| |
| public static Vector3f convertToVector3f(javax.vecmath.Tuple3d tuple3d) { |
| return new Vector3f((float) tuple3d.x, (float) tuple3d.y, (float) tuple3d.z); |
| } |
| |
| public static javax.vecmath.Vector3f convertToJavaxVector3f(Vector3f vector3f) { |
| return new javax.vecmath.Vector3f(vector3f.x, vector3f.y, vector3f.z); |
| } |
| |
| public static Texture2D createTexture2D(BufferedImage bufferedImage, AssetManager assetManager) { |
| AWTLoader awtLoader = new AWTLoader(); |
| com.jme3.texture.Image img = awtLoader.load(bufferedImage, true); |
| Texture2D texture = new Texture2D(img); |
| |
| return texture; |
| } |
| |
| public static Material createMaterial(BufferedImage bufferedImage, AssetManager assetManager) { |
| Texture2D texture = createTexture2D(bufferedImage, assetManager); |
| |
| Material material = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); |
| material.setTexture("ColorMap", texture); |
| |
| return material; |
| } |
| |
| public static com.jme3.renderer.queue.RenderQueue.ShadowMode convertToJMEShadowMode(ShadowMode shadowMode) { |
| com.jme3.renderer.queue.RenderQueue.ShadowMode mode = com.jme3.renderer.queue.RenderQueue.ShadowMode.Inherit; |
| |
| switch (shadowMode.getValue()) { |
| case ShadowMode.OFF_VALUE: |
| mode = com.jme3.renderer.queue.RenderQueue.ShadowMode.Off; |
| break; |
| |
| case ShadowMode.INHERIT_VALUE: |
| mode = com.jme3.renderer.queue.RenderQueue.ShadowMode.Inherit; |
| break; |
| |
| case ShadowMode.CAST_VALUE: |
| mode = com.jme3.renderer.queue.RenderQueue.ShadowMode.Cast; |
| break; |
| |
| case ShadowMode.RECEIVE_VALUE: |
| mode = com.jme3.renderer.queue.RenderQueue.ShadowMode.Receive; |
| break; |
| |
| case ShadowMode.CAST_AND_RECEIVE_VALUE: |
| mode = com.jme3.renderer.queue.RenderQueue.ShadowMode.CastAndReceive; |
| break; |
| |
| default: |
| break; |
| } |
| |
| return mode; |
| } |
| |
| public static String sceneTopologyAsHTML(Spatial root) { |
| return expandSpatialAsHTML(root); |
| } |
| |
| public static OS getOS() { |
| if (os == OS.UNINITIALIZED) { |
| String osName = System.getProperty("os.name"); |
| if (osName.startsWith("Windows")) { |
| os = OS.WINDOWS; |
| } else if (osName.startsWith("Linux")) { |
| os = OS.LINUX; |
| } else if (osName.startsWith("Mac")) { |
| os = OS.MACOS; |
| } |
| } |
| |
| return os; |
| } |
| |
| private static String expandSpatialAsHTML(com.jme3.scene.Spatial spatial) { |
| String s = new String("<!DOCTYPE html>\n"); |
| s += "\t<html>\n"; |
| s += "\t\t<head>\n"; |
| s += "\t\t\t<script type='text/javascript' src='https://www.google.com/jsapi'></script>\n"; |
| s += "\t\t\t<script type='text/javascript'>\n"; |
| s += "\t\t\t google.load('visualization', '1', {packages:['orgchart']});\n"; |
| s += "\t\t\t google.setOnLoadCallback(drawChart);\n"; |
| s += "\t\t\t function drawChart() {\n"; |
| s += "\t\t\t\t var data = new google.visualization.DataTable();\n"; |
| s += "\t\t\t\t data.addColumn('string', 'Node');\n"; |
| s += "\t\t\t\t data.addColumn('string', 'Parent')\n;"; |
| s += "\t\t\t\t data.addRows(["; |
| |
| Map<com.jme3.scene.Spatial, String> spatialToNameMap = new HashMap<com.jme3.scene.Spatial, String>(); |
| List<String[]> nodeParentList = new ArrayList<String[]>(); |
| |
| expandSpatialAsHTMLRecursive(spatialToNameMap, nodeParentList, spatial); |
| |
| Iterator<String[]> it = nodeParentList.iterator(); |
| while (it.hasNext()) { |
| String[] parentNode = it.next(); |
| s += "\t\t\t\t\t['" + parentNode[0] + "' , '" + parentNode[1] + "']"; |
| |
| if (it.hasNext()) { |
| s += ",\n"; |
| } else { |
| s += "\n"; |
| } |
| } |
| |
| s += "\t\t\t\t ]);\n"; |
| s += "\t\t\t\t var chart = new google.visualization.OrgChart(document.getElementById('chart_div'));\n"; |
| s += "\t\t\t\t chart.draw(data);\n"; |
| s += "\t\t\t}\n"; |
| s += "\t\t\t</script>\n"; |
| s += "\t\t</head>\n"; |
| s += "\t<body>\n"; |
| s += "\t\t<div id='chart_div'></div>\n"; |
| s += "\t</body>\n"; |
| s += "</html>\n"; |
| |
| return s; |
| } |
| |
| private static void expandSpatialAsHTMLRecursive(Map<com.jme3.scene.Spatial, String> spatialToNameMap, |
| List<String[]> nodeParentList, com.jme3.scene.Spatial spatial) { |
| // Adds the spatial to the map. |
| String nodeName = getNameForSpatial(spatial); |
| spatialToNameMap.put(spatial, nodeName); |
| |
| // Adds the spatial and its parent to the nodeParentList. |
| String parentName = spatialToNameMap.get(spatial.getParent()); |
| if (parentName == null) |
| parentName = ""; |
| String[] nodeParent = new String[] { nodeName, parentName }; |
| nodeParentList.add(nodeParent); |
| |
| if (spatial instanceof Node) { |
| com.jme3.scene.Node parent = (com.jme3.scene.Node) spatial; |
| |
| for (Spatial child : parent.getChildren()) { |
| expandSpatialAsHTMLRecursive(spatialToNameMap, nodeParentList, child); |
| } |
| } |
| } |
| |
| private static String getNameForSpatial(com.jme3.scene.Spatial spatial) { |
| String s = new String(); |
| |
| if (spatial.getName() != null) { |
| s += spatial.getName().replaceAll(" ", "_") + "(" + Integer.toString(spatial.hashCode()) + ")"; |
| } else { |
| s += Integer.toString(spatial.hashCode()); |
| } |
| |
| return s; |
| } |
| } |