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 */