PtolemyCreatePluginDataLoad: IconPlugin.java

File IconPlugin.java, 9.3 kB (added by antonio, 20 months ago)
Line 
1/**
2 * Ptolemy3D - a Java-based 3D Viewer for GeoWeb applications.
3 * Copyright (C) 2008 Mark W. Korver
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18package org.ptolemy3d.plugin;
19
20import com.sun.opengl.util.texture.Texture;
21import com.sun.opengl.util.texture.TextureCoords;
22import com.sun.opengl.util.texture.TextureIO;
23import java.awt.image.BufferedImage;
24import java.util.logging.Level;
25import java.util.logging.Logger;
26import java.io.IOException;
27import java.net.URL;
28import javax.imageio.ImageIO;
29import javax.media.opengl.GL;
30import javax.media.opengl.glu.GLU;
31import org.ptolemy3d.Ptolemy3D;
32import org.ptolemy3d.Ptolemy3DConfiguration;
33import org.ptolemy3d.Ptolemy3DUnit;
34import org.ptolemy3d.io.Communicator;
35import org.ptolemy3d.math.Math3D;
36import org.ptolemy3d.scene.Landscape;
37import org.ptolemy3d.scene.Plugin;
38import org.ptolemy3d.view.Camera;
39
40/**
41 * IconPlugin shows an image at the specified position.
42 *
43 * @author Antonio Santiago <asantiagop@gmail.com>
44 */
45public class IconPlugin implements Plugin
46{
47
48    private static final String NAME = "ICON_PLUGIN_";
49    private int index = -1;
50    private boolean status = true;
51    //
52    private String imageName = "";
53    private double latitude = 0;
54    private double longitude = 0;
55    //
56    private Ptolemy3D ptolemy = null;
57    private GL gl = null;
58    //
59    private boolean iconLoaded = false;
60    private boolean errorLoading = false;
61    private boolean initTexture = false;
62    private BufferedImage bufferedImage = null;
63    private Texture texture = null;
64
65    public void init(Ptolemy3D ptolemy)
66    {
67        this.ptolemy = ptolemy;
68    }
69
70    public void setPluginIndex(int index)
71    {
72        this.index = index;
73    }
74
75    public void setPluginParameters(String params)
76    {
77        String values[] = params.split(",");
78        imageName = values[0];
79        latitude = Double.valueOf(values[1]);
80        longitude = Double.valueOf(values[2]);
81    }
82
83    public void motionStop(GL gl)
84    {
85    }
86
87    public boolean pick(double[] intersectPoint, double[][] ray)
88    {
89        return false;
90    }
91
92    public boolean onPick(double[] intersectPoint)
93    {
94        return false;
95    }
96
97    public void tileLoaderAction(Communicator com) throws IOException
98    {
99    }
100
101    public String pluginAction(String commandname, String command_params)
102    {
103        if (commandname.equalsIgnoreCase("status"))
104        {
105            status = (Integer.parseInt(command_params) == 1) ? true : false;
106        }
107        else if (commandname.equalsIgnoreCase("getLayerName"))
108        {
109            return NAME + index;
110        }
111        return null;
112    }
113
114    public void reloadData()
115    {
116    }
117
118    public void initGL(GL gl)
119    {
120        if (!iconLoaded)
121        {
122
123            Thread newThread = new Thread(new Runnable()
124            {
125
126                public void run()
127                {
128                    URL url;
129                    try
130                    {
131                        String server = ptolemy.configuration.server;
132                        url = new URL("http://" + server + imageName);
133                        bufferedImage = ImageIO.read(url);
134                    }
135                    catch (IOException ex)
136                    {
137                        Logger.getLogger(IconPlugin.class.getName()).log(Level.SEVERE, null, ex);
138                        errorLoading = true;
139                    }
140                    finally
141                    {
142                        iconLoaded = true;
143                    }
144                }
145            });
146
147            newThread.start();
148        }
149    }
150
151    /**
152     * Renders the icon.
153     *
154     * @param gl
155     */
156    public void draw(GL gl)
157    {
158        // Check if our point is in the visible side of the globe.
159        if (!isPointInView(longitude, latitude))
160        {
161            return;
162        }
163
164        // If the icon image is not loaded return or there was an error loading
165        // it then returns.
166        if (!iconLoaded || errorLoading)
167        {
168            return;
169        }
170
171        // Initiallize the texture
172        if (!initTexture)
173        {
174            initTexture = true;
175            texture = TextureIO.newTexture(bufferedImage, false);
176        }
177
178        this.gl = gl;
179
180        // Store previous matrices
181        gl.glMatrixMode(GL.GL_PROJECTION);
182        gl.glPushMatrix();
183        gl.glMatrixMode(GL.GL_MODELVIEW);
184        gl.glPushMatrix();
185
186        // Store attributes that will change
187        gl.glPushAttrib(GL.GL_CURRENT_BIT | GL.GL_ENABLE_BIT | GL.GL_COLOR_BUFFER_BIT);
188
189        gl.glEnable(GL.GL_BLEND);
190        gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
191
192        // Compute coordinates
193        Ptolemy3DUnit unit = ptolemy.unit;
194
195        double point[] = computeCartesianSurfacePoint(latitude, longitude);
196        point[0] += 5 * unit.coordSystemRatio;
197        point[1] += 5 * unit.coordSystemRatio;
198        point[2] += 5 * unit.coordSystemRatio;
199
200        // Get screen coordinates before altering projection and modelview matrices.
201        double scr[] = worldToScreen(point);
202
203        // Set an orthographic projection.
204        int viewport[] = new int[4];
205        gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
206        gl.glMatrixMode(GL.GL_PROJECTION);
207        gl.glLoadIdentity();
208        gl.glOrtho(0.0f, viewport[2], 0.0f, viewport[3], -1.0f, 1.0f);
209        gl.glMatrixMode(GL.GL_MODELVIEW);
210        gl.glLoadIdentity();
211
212        // Bind texture and draw icon
213        texture.bind();
214        TextureCoords textureCoords = texture.getImageTexCoords();
215        int width = texture.getImageWidth();
216        int height = texture.getImageHeight();
217
218        gl.glBegin(GL.GL_QUADS);
219        gl.glTexCoord2f(textureCoords.left(), textureCoords.bottom());
220        gl.glVertex2d(scr[0], scr[1]);
221
222        gl.glTexCoord2f(textureCoords.right(), textureCoords.bottom());
223        gl.glVertex2d(scr[0] + width, scr[1]);
224
225        gl.glTexCoord2f(textureCoords.right(), textureCoords.top());
226        gl.glVertex2d(scr[0] + width, scr[1] + height);
227
228        gl.glTexCoord2f(textureCoords.left(), textureCoords.top());
229        gl.glVertex2d(scr[0], scr[1] + height);
230        gl.glEnd();
231
232        // Restore attributes
233        gl.glPopAttrib();
234
235        // Restore matrices
236        gl.glMatrixMode(GL.GL_MODELVIEW);
237        gl.glPopMatrix();
238        gl.glMatrixMode(GL.GL_PROJECTION);
239        gl.glPopMatrix();
240    }
241
242    /**
243     * Checks if a point is the visible side of the globe.
244     * @param lon
245     * @param lat
246     * @return
247     */
248    public static boolean isPointInView(double lon, double lat)
249    {
250        final Camera camera = Ptolemy3D.ptolemy.camera;
251
252        lat *= 1000000;
253        lon *= 1000000;
254
255        //View forward vector
256        double[] forward =
257        {
258            -camera.cameraMat.m[0][2], -camera.cameraMat.m[1][2], -camera.cameraMat.m[2][2]
259        };
260
261        //Normal on the globe
262        double[] point = new double[3];
263        Math3D.setSphericalCoord(lon, lat, point);
264
265        //Angle between vector (front/back face test)
266        double dot = (forward[0] * point[0]) + (forward[1] * point[1]) + (forward[2] * point[2]);
267        if (dot <= 0)
268        {
269            return true;
270        }
271        else
272        {
273            return false;
274        }
275    }
276
277    /**
278     * Converts a lat/lot position into a cartesion space.
279     * @param lat
280     * @param lon
281     * @return
282     */
283    private double[] computeCartesianSurfacePoint(double lat, double lon)
284    {
285
286        Landscape landscape = ptolemy.scene.landscape;
287
288        lat *= 1000000;
289        lon *= 1000000;
290
291        // Transform from lat/lon to cartesion coordinates.
292        double point[] = new double[3];
293        Math3D.setSphericalCoord(lon, lat, point);
294
295        // Get the terrain elevation
296        double terrainElev = landscape.groundHeight(lon, lat, 0);
297
298        point[0] *= (Ptolemy3DConfiguration.EARTH_RADIUS + terrainElev);
299        point[1] *= (Ptolemy3DConfiguration.EARTH_RADIUS + terrainElev);
300        point[2] *= (Ptolemy3DConfiguration.EARTH_RADIUS + terrainElev);
301
302        return point;
303    }
304
305    /**
306     * Projects a cartesion point in the camera space and returns the pixel
307     * position in OpenGL coordinate space, that is, (0,0) at bottom-lect.
308     * @param cartesian
309     */
310    private double[] worldToScreen(double[] cartesian)
311    {
312        GLU glu = new GLU();
313        double model[] = new double[16];
314        double proj[] = new double[16];
315        int viewport[] = new int[4];
316
317        gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX, model, 0);
318        gl.glGetDoublev(GL.GL_PROJECTION_MATRIX, proj, 0);
319        gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
320
321        double screen[] = new double[4];
322        glu.gluProject(cartesian[0], cartesian[1], cartesian[2], model, 0, proj, 0, viewport, 0, screen, 0);
323
324        return screen;
325    }
326
327    public void destroyGL(GL gl)
328    {
329    }
330}