001/** 002 * Copyright (c) 2011, The University of Southampton and the individual contributors. 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without modification, 006 * are permitted provided that the following conditions are met: 007 * 008 * * Redistributions of source code must retain the above copyright notice, 009 * this list of conditions and the following disclaimer. 010 * 011 * * Redistributions in binary form must reproduce the above copyright notice, 012 * this list of conditions and the following disclaimer in the documentation 013 * and/or other materials provided with the distribution. 014 * 015 * * Neither the name of the University of Southampton nor the names of its 016 * contributors may be used to endorse or promote products derived from this 017 * software without specific prior written permission. 018 * 019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 029 */ 030/** 031 * 032 */ 033package org.openimaj.vis.general; 034 035import java.awt.Font; 036import java.awt.geom.Rectangle2D; 037 038import javax.media.opengl.GL; 039import javax.media.opengl.GL2; 040import javax.media.opengl.GLAutoDrawable; 041import javax.media.opengl.fixedfunc.GLLightingFunc; 042import javax.media.opengl.fixedfunc.GLMatrixFunc; 043 044import org.openimaj.image.colour.RGBColour; 045import org.openimaj.vis.DataUnitsTransformer; 046 047import com.jogamp.opengl.util.awt.TextRenderer; 048 049 050/** 051 * A class for drawing rulers in a 3D world. 052 * 053 * // TODO : This could be made more efficient using DisplayLists. 054 * 055 * @author David Dupplaw (dpd@ecs.soton.ac.uk) 056 * @created 8 Jul 2013 057 */ 058public class AxisRenderer3D 059 extends AxisRenderer<float[]> 060 implements DataUnitsTransformer<float[], Double, Double> 061{ 062 /** The OpenGL surface we're rendering to */ 063 private GLAutoDrawable glad; 064 065 /** The length of the axis */ 066 private final double axisLength = 1; 067 068 private int gridDirection = 1; 069 070 private final TextRenderer textRenderer; 071 072 /** 073 * Default constructor sets some default axis values 074 */ 075 public AxisRenderer3D() 076 { 077 Float[] c = RGBColour.WHITE; 078 this.config.getRenderingConfig().setColour( new float[]{ c[0], c[1], c[2] } ); 079 c = RGBColour.GRAY; 080 this.config.getRenderingConfig().setMajorTickColour( new float[]{ c[0], c[1], c[2] } ); 081 this.config.getRenderingConfig().setMajorGridColour( new float[]{ c[0], c[1], c[2] } ); 082 this.config.getRenderingConfig().setMinorTickColour( new float[]{ c[0], c[1], c[2] } ); 083 c = new Float[] {0.3f,0.3f,0.3f}; 084 this.config.getRenderingConfig().setMinorGridColour( new float[]{ c[0], c[1], c[2] } ); 085 this.config.getRenderingConfig().setMajorTickLength( 0.04 ); 086 this.config.getRenderingConfig().setMinorTickLength( 0.01 ); 087 this.config.getRenderingConfig().setMajorTickSpacing( 1 ); 088 this.config.getRenderingConfig().setMinorTickSpacing( 0.5 ); 089 090 this.config.getRenderingConfig().setThickness( 3 ); 091 this.config.getRenderingConfig().setMajorTickThickness( 1 ); 092 this.config.getRenderingConfig().setMinorTickThickness( 0.5 ); 093 094 this.textRenderer = new TextRenderer( new Font( "SansSerif", Font.BOLD, 36 ) ); 095 } 096 097 @Override 098 public void drawAxis( final AxisConfig<float[]> config ) 099 { 100 final GL2 gl = this.glad.getGL().getGL2(); 101 102 gl.glPushMatrix(); 103 104 this.orient( gl ); 105 106 final float zero = 0.001f; 107 gl.glBegin( GL.GL_LINE_STRIP ); 108 { 109 gl.glLineWidth( (float)config.getRenderingConfig().getThickness() ); 110 gl.glColor3f( config.getRenderingConfig().getColour()[0], 111 config.getRenderingConfig().getColour()[1], 112 config.getRenderingConfig().getColour()[2] ); 113 114 final float n1 = this.calculatePosition( config.getMinValue() ).floatValue(); 115 final float n2 = this.calculatePosition( config.getMaxValue() ).floatValue(); 116 117 // We draw in the x axis, so the orientation has to be set appropriately 118 gl.glVertex3f( n1, zero, zero ); 119 gl.glVertex3f( n2, zero, zero ); 120 } 121 gl.glEnd(); 122 123 gl.glPopMatrix(); 124 } 125 126 @Override 127 public void drawAxisLabel( final AxisConfig<float[]> config ) 128 { 129 final GL2 gl = this.glad.getGL().getGL2(); 130 131 gl.glPushMatrix(); 132// this.orient( gl ); 133 134 final double[] o = this.config.getRenderingConfig().getNameOrientation(); 135 if( o != null ) 136 { 137 for( int i = 0; i < o.length; i += 4 ) 138 gl.glRotated( o[i], o[i+1], o[i+2], o[i+3] ); 139 } 140 141 this.textRenderer.begin3DRendering(); 142 { 143 gl.glMatrixMode( GLMatrixFunc.GL_MODELVIEW ); 144 145 // TODO: Text colour and size 146 this.textRenderer.setColor( 1.0f, 0.2f, 0.2f, 0.8f ); 147 final float scale = 0.003f; 148 149 final Rectangle2D nameBounds = this.textRenderer.getBounds( config.getName() ); 150 this.textRenderer.draw3D( config.getName(), (float)(1-nameBounds.getWidth()*scale), 151 (float)(-nameBounds.getHeight()*scale) 152 *config.getRenderingConfig().getNameDirection(), 0.1f, scale ); 153 } 154 this.textRenderer.end3DRendering(); 155 gl.glPopMatrix(); 156 } 157 158 @Override 159 public void drawMajorTick( final double location, final AxisConfig<float[]> config ) 160 { 161 final GL2 gl = this.glad.getGL().getGL2(); 162 163 gl.glPushMatrix(); 164 165 this.orient( gl ); 166 167 gl.glLineWidth( (float)config.getRenderingConfig().getMajorTickThickness() ); 168 gl.glColor3f( config.getRenderingConfig().getMajorTickColour()[0], 169 config.getRenderingConfig().getMajorTickColour()[1], 170 config.getRenderingConfig().getMajorTickColour()[2] ); 171 172 final float l = (float)config.getRenderingConfig().getMajorTickLength(); 173 final float l2 = -l; 174 175 final float ll = this.calculatePosition( location ).floatValue(); 176 177 final float zero = 0.001f; 178 gl.glBegin( GL.GL_LINE_STRIP ); 179 { 180 // We draw in the x axis, so the orientation has to be set appropriately 181 gl.glVertex3f( ll, l, zero ); 182 gl.glVertex3f( ll, l2, zero ); 183 } 184 gl.glEnd(); 185 186 gl.glBegin( GL.GL_LINE_STRIP ); 187 { 188 // We draw in the x axis, so the orientation has to be set appropriately 189 gl.glVertex3f( ll, zero, l ); 190 gl.glVertex3f( ll, zero, l2 ); 191 } 192 gl.glEnd(); 193 194 gl.glPopMatrix(); 195 } 196 197 @Override 198 public void drawMajorTickGridline( final double location, final AxisConfig<float[]> config ) 199 { 200 final GL2 gl = this.glad.getGL().getGL2(); 201 202 gl.glPushMatrix(); 203 204 this.orient( gl ); 205 206 gl.glLineWidth( (float)config.getRenderingConfig().getMajorGridThickness() ); 207 gl.glColor3f( config.getRenderingConfig().getMajorGridColour()[0], 208 config.getRenderingConfig().getMajorGridColour()[1], 209 config.getRenderingConfig().getMajorGridColour()[2] ); 210 211 final float ll = this.calculatePosition( location ).floatValue(); 212 213 final float zero = 0.001f; 214 gl.glBegin( GL.GL_LINE_STRIP ); 215 { 216 // We draw in the x axis, so the orientation has to be set appropriately 217 gl.glVertex3f( ll, zero, zero ); 218 gl.glVertex3f( ll, 1, zero ); 219 } 220 gl.glEnd(); 221 222 gl.glBegin( GL.GL_LINE_STRIP ); 223 { 224 // We draw in the x axis, so the orientation has to be set appropriately 225 gl.glVertex3f( ll, zero, zero ); 226 gl.glVertex3f( ll, zero, 1*this.gridDirection ); 227 } 228 gl.glEnd(); 229 230 gl.glPopMatrix(); 231 } 232 233 @Override 234 public void drawMinorTick( final double location, final AxisConfig<float[]> config ) 235 { 236 final GL2 gl = this.glad.getGL().getGL2(); 237 238 gl.glPushMatrix(); 239 240 this.orient( gl ); 241 242 final float zero = 0.001f; 243 gl.glBegin( GL.GL_LINE_STRIP ); 244 { 245// gl.glEnable( GL2.GL_LINE_STIPPLE ); 246// gl.glLineStipple( 2, (short) 0x00FF ); 247 gl.glLineWidth( (float)config.getRenderingConfig().getMinorTickThickness() ); 248 gl.glColor3f( config.getRenderingConfig().getMinorTickColour()[0], 249 config.getRenderingConfig().getMinorTickColour()[1], 250 config.getRenderingConfig().getMinorTickColour()[2] ); 251 252 final float l = (float)config.getRenderingConfig().getMinorTickLength(); 253 final float l2 = -l; 254 255 final float ll = this.calculatePosition( location ).floatValue(); 256 257 // We draw in the x axis, so the orientation has to be set appropriately 258 gl.glVertex3f( ll, l, zero ); 259 gl.glVertex3f( ll, l2, zero ); 260 } 261 gl.glEnd(); 262 263 gl.glPopMatrix(); 264 } 265 266 @Override 267 public void drawMinorTickGridline( final double location, final AxisConfig<float[]> config ) 268 { 269 final GL2 gl = this.glad.getGL().getGL2(); 270 271 gl.glPushMatrix(); 272 273 this.orient( gl ); 274 275 gl.glLineWidth( (float)config.getRenderingConfig().getMinorGridThickness() ); 276 gl.glColor3f( config.getRenderingConfig().getMinorGridColour()[0], 277 config.getRenderingConfig().getMinorGridColour()[1], 278 config.getRenderingConfig().getMinorGridColour()[2] ); 279 final float[] rgba = { config.getRenderingConfig().getMinorGridColour()[0], 280 config.getRenderingConfig().getMinorGridColour()[1], 281 config.getRenderingConfig().getMinorGridColour()[2] }; 282 gl.glMaterialfv( GL.GL_FRONT, GLLightingFunc.GL_AMBIENT, rgba, 0); 283 gl.glMaterialfv( GL.GL_FRONT, GLLightingFunc.GL_SPECULAR, rgba, 0); 284 gl.glMaterialf( GL.GL_FRONT, GLLightingFunc.GL_SHININESS, 0f); 285 286 final float ll = this.calculatePosition( location ).floatValue(); 287 288 final float zero = 0.001f; 289 gl.glBegin( GL.GL_LINE_STRIP ); 290 { 291 // We draw in the x axis, so the orientation has to be set appropriately 292 gl.glVertex3f( ll, zero, zero ); 293 gl.glVertex3f( ll, 1, zero ); 294 } 295 gl.glEnd(); 296 297 gl.glBegin( GL.GL_LINE_STRIP ); 298 { 299 // We draw in the x axis, so the orientation has to be set appropriately 300 gl.glVertex3f( ll, zero, zero ); 301 gl.glVertex3f( ll, zero, 1*this.gridDirection ); 302 } 303 gl.glEnd(); 304 305 gl.glPopMatrix(); 306 } 307 308 private void orient( final GL2 gl ) 309 { 310 if( this.config.getOrientation()[0] != 0 ) 311 { 312 gl.glMatrixMode( GLMatrixFunc.GL_MODELVIEW ); 313 final double[] o = this.config.getOrientation(); 314 for( int i = 0; i < o.length; i+=4 ) 315 gl.glRotated( o[i], o[i+1], o[i+2], o[i+3] ); 316 } 317 } 318 319 /** 320 * @param glad 321 */ 322 public void setGLAD( final GLAutoDrawable glad ) 323 { 324 this.glad = glad; 325 } 326 327 @Override 328 public Double calculatePosition( final Double units ) 329 { 330 return this.axisLength/(this.config.getMaxValue()-this.config.getMinValue()) * units; 331 } 332 333 @Override 334 public Double calculateUnitsAt( final Double position ) 335 { 336 return position / (this.axisLength/(this.config.getMaxValue()-this.config.getMinValue())); 337 } 338 339 /** 340 * @param i 341 */ 342 public void setGridDirection( final int i ) 343 { 344 this.gridDirection = i; 345 } 346 347 @Override 348 public Double scaleDimension( final Double dimension ) 349 { 350 return dimension * (this.axisLength/(this.config.getMaxValue()-this.config.getMinValue())); 351 } 352}