View Javadoc

1   /*
2    * Copyright (c) 2003-2008 by Cosylab d. d.
3    *
4    * This file is part of CosyBeans-Common.
5    *
6    * CosyBeans-Common is free software: you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation, either version 3 of the License, or
9    * (at your option) any later version.
10   *
11   * CosyBeans-Common is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   * You should have received a copy of the GNU General Public License
17   * along with CosyBeans-Common.  If not, see <http://www.gnu.org/licenses/>.
18   */
19  
20  package com.cosylab.gui.components.ledder;
21  import java.awt.Color;
22  
23  /**
24   * This is a specialized class for rendering LED icons. It is implemented as a
25   * minimal ray-tracer with specular lighting overlay rendering.<p>
26   * NOTE: Due to performance reasons this class is not thread-safe and should 
27   * not be shared in multiple instances.
28   * 
29   * @author <a href="mailto:ales.pucelj@cosylab.com">Ales Pucelj</a>
30   * @version $id$
31   */
32  public class LedRendererOld {
33  
34  	private int centerX;
35  	private int centerY;
36  
37  	private double radiusOffset;
38  
39  	private int radius;
40  
41  	private int red;
42  	private int green;
43  	private int blue;
44  
45  	private double highlightFactor = 0.85;
46  	private double highlightFocus = 3;
47  
48  	private double shadowIntensity = 1.5;
49  
50  	private final float[] colorHSB = new float[3];
51  
52  	private double[] light = getLight(-0.2, -0.5, new double[3]);
53  
54  	/**
55  	 * @param x int
56  	 * @param y int
57  	 * @param r int
58  	 * @param lpp LedPaintParameters
59  	 */
60  	public LedRendererOld(int x, int y, int r, LedPaintParameters lpp) {
61  		super();
62  
63  		centerX = x;
64  		centerY = y;
65  		radius = r;
66  
67  		light = getLight(lpp.lightX, lpp.lightY, new double[3]);
68  
69  		highlightFactor = lpp.highlightFactor;
70  		highlightFocus = lpp.highlightFocus;
71  
72  		shadowIntensity = lpp.shadowIntensity;
73  
74  		radiusOffset = (1 - lpp.borderSize) * radius;
75  
76  		red = lpp.color.getRed();
77  		green = lpp.color.getGreen();
78  		blue = lpp.color.getBlue();
79  	}
80  
81  	/**
82  	 * @param v double[]
83  	 * @return double
84  	 */
85  	private static double vLen(final double[] v) {
86  		return Math.sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
87  	}
88  
89  	/**
90  	 * @param x double
91  	 * @param y double
92  	 * @param r double
93  	 * @return double
94  	 */
95  	private static final double getZ(
96  		final double x,
97  		final double y,
98  		final double r) {
99  
100 		return Math.sqrt(r * r - x * x - y * y);
101 	}
102 
103 	/**
104 	 * @param v double[]
105 	 * @return double[]
106 	 */
107 	private static final double[] norm(final double[] v) {
108 		double l = vLen(v);
109 		v[0] /= l;
110 		v[1] /= l;
111 		v[2] /= l;
112 
113 		return v;
114 	}
115 
116 	/**
117 	 * @param x double
118 	 * @param p double
119 	 * @return float
120 	 */
121 	private final float getHighlight(double x, final double p) {
122 
123 		x = (x - highlightFactor) / (1 - highlightFactor);
124 
125 		return (float) ((x < 0) ? p : p * (1 - Math.pow(x, highlightFocus)));
126 	}
127 
128 	/**
129 	 * @param x double
130 	 * @param p double
131 	 * @return float
132 	 */
133 	private final float getIntensity(final double x, final double p) {
134 		return (float) (p * Math.pow(x, shadowIntensity));
135 //		return (float) (p * x * x * shadowIntensity);
136 	}
137 
138 	/**
139 	 * @param angle double
140 	 * @return int
141 	 */
142 	private final int getColor(final double angle) {
143 		Color.RGBtoHSB(red, green, blue, colorHSB);
144 
145 		return Color.HSBtoRGB(
146 			colorHSB[0],
147 			getHighlight(angle, colorHSB[1]),
148 			getIntensity(angle, colorHSB[2]));
149 	}
150 
151 	/**
152 	 * @param x double
153 	 * @param y double
154 	 * @param v double[]
155 	 * @return double[]
156 	 */
157 	public double[] getLight(double x, double y, double[] v) {
158 		v[0] = x;
159 		v[1] = y;
160 		v[2] = getZ(x, y, 1);
161 
162 		return norm(v);
163 	}
164 
165  /*
166 	public int[] renderSectionOld(int x, int y, int w, int h) {
167 
168 		int[] data = new int[w * h * 4];
169 
170 		int col = 0;
171 		int base = 0;
172 
173 		for (int py = 0; py < h; py++) {
174 
175 			base = 4 * (py * w);
176 
177 			for (int px = 0; px < w; px++) {
178 				n[0] = x + px - centerX;
179 				n[1] = y + py - centerY;
180 				n[2] = 0.0;
181 
182 				double l = vLen(n);
183 
184 				if (l < radiusOffset) {
185 					n[2] = getZ(n[0], n[1], radius);
186 
187 					col = getColor((1 + dot(norm(n), light)) / 2);
188 				} else {
189 					col = (l <= radius) ? 0xFF000000 : 0x0;
190 				}
191 
192 				data[base + 0] = (col >> 0x10) & 0xFF;
193 				data[base + 1] = (col >> 0x08) & 0xFF;
194 				data[base + 2] = (col >> 0x00) & 0xFF;
195 				data[base + 3] = (col >> 0x18) & 0xFF;
196 
197 				base += 4;
198 			}
199 		}
200 		return data;
201 	}
202 	 */
203 
204 	/**
205 	 * @param x int
206 	 * @param y int
207 	 * @param w int
208 	 * @param h int
209 	 * @return int[]
210 	 */
211 	public final int[] renderSection(
212 		final int x,
213 		final int y,
214 		final int w,
215 		final int h) {
216 
217 		int[] data = new int[w * h * 4];
218 
219 		int col = 0;
220 		int base = 0;
221 
222 		int ro1 = (int) radiusOffset * (int) radiusOffset;
223 		int ro2 = radius * radius;
224 
225 		for (int py = 0; py < h; py++) {
226 
227 			base = 4 * (py * w);
228 			int dy = y + py - centerY;
229 
230 			for (int px = 0; px < w; px++) {
231 				int dx = x + px - centerX;
232 
233 				// double l = vLen(n);
234 				int l = dx * dx + dy * dy;
235 
236 				if (l < ro1) {
237 					// n[2] = getZ(n[0], n[1], radius);
238 					int dz = (int) Math.sqrt(ro2 - l);
239 
240 					double dot = dx * light[0] + dy * light[1] + dz * light[2];
241 
242 					//					double norm = Math.sqrt(dx * dx + dy * dy + dz * dz);
243 
244 					// col = getColor((1 + dot(norm(n), light)) / 2);
245 					//					col = getColor((1 + dot / norm) / 2);
246 					double angle = (1 + dot / radius) / 2;
247 
248 					col = getColor(angle);
249 
250 				} else {
251 					col = (l <= ro2) ? 0xFF000000 : 0x0;
252 				}
253 
254 				data[base + 0] = (col >> 0x10) & 0xFF;
255 				data[base + 1] = (col >> 0x08) & 0xFF;
256 				data[base + 2] = (col >> 0x00) & 0xFF;
257 				data[base + 3] = (col >> 0x18) & 0xFF;
258 
259 				base += 4;
260 			}
261 		}
262 		return data;
263 	}
264 }
265 
266 /*
267 					double saturation;
268 					double hue = 0;
269 
270 					int cmin = (red < green) ? red : green;
271 					cmin = (cmin < blue) ? cmin : blue;
272 
273 					int cmax = (red > green) ? red : green;
274 					cmax = (cmax > blue) ? red : blue;
275 
276 					int delta = cmax - cmin;
277 
278 					saturation = (cmax == 0) ? 0 : delta / cmax;
279 
280 					if (saturation == 0) {
281 						hue = 0;
282 					} else
283 					if (red == cmax) {
284 						hue = 60 * (green - blue) / delta;
285 					} else {
286 						if (green == cmax) {
287 							hue = 120 + 60 * (blue - red) / delta;
288 						} else {
289 							if (blue == cmax) {
290 								hue = 240 + 60 * (red - green) / delta;
291 							}
292 						}
293 					}
294 					if (hue < 0) {
295 						hue += 360;
296 					}
297 */