001: /*
002:
003: Licensed to the Apache Software Foundation (ASF) under one or more
004: contributor license agreements. See the NOTICE file distributed with
005: this work for additional information regarding copyright ownership.
006: The ASF licenses this file to You under the Apache License, Version 2.0
007: (the "License"); you may not use this file except in compliance with
008: the License. You may obtain a copy of the License at
009:
010: http://www.apache.org/licenses/LICENSE-2.0
011:
012: Unless required by applicable law or agreed to in writing, software
013: distributed under the License is distributed on an "AS IS" BASIS,
014: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: See the License for the specific language governing permissions and
016: limitations under the License.
017:
018: */
019: package org.apache.batik.ext.awt.image;
020:
021: import java.awt.Color;
022:
023: /**
024: * A light source which emits a light of constant intensity in all directions.
025: *
026: * @author <a href="mailto:vincent.hardy@eng.sun.com">Vincent Hardy</a>
027: * @version $Id: SpotLight.java 501495 2007-01-30 18:00:36Z dvholten $
028: */
029: public class SpotLight extends AbstractLight {
030: /**
031: * The light position, in user space
032: */
033: private double lightX, lightY, lightZ;
034:
035: /**
036: * Point where the light points to
037: */
038: private double pointAtX, pointAtY, pointAtZ;
039:
040: /**
041: * Specular exponent (light focus)
042: */
043: private double specularExponent;
044:
045: /**
046: * Limiting cone angle
047: */
048: private double limitingConeAngle, limitingCos;
049:
050: /**
051: * Light direction vector
052: */
053: private final double[] S = new double[3];
054:
055: /**
056: * @return the light's x position
057: */
058: public double getLightX() {
059: return lightX;
060: }
061:
062: /**
063: * @return the light's y position
064: */
065: public double getLightY() {
066: return lightY;
067: }
068:
069: /**
070: * @return the light's z position
071: */
072: public double getLightZ() {
073: return lightZ;
074: }
075:
076: /**
077: * @return x-axis coordinate where the light points to
078: */
079: public double getPointAtX() {
080: return pointAtX;
081: }
082:
083: /**
084: * @return y-axis coordinate where the light points to
085: */
086: public double getPointAtY() {
087: return pointAtY;
088: }
089:
090: /**
091: * @return z-axis coordinate where the light points to
092: */
093: public double getPointAtZ() {
094: return pointAtZ;
095: }
096:
097: /**
098: * @return light's specular exponent (focus)
099: */
100: public double getSpecularExponent() {
101: return specularExponent;
102: }
103:
104: /**
105: * @return light's limiting cone angle
106: */
107: public double getLimitingConeAngle() {
108: return limitingConeAngle;
109: }
110:
111: public SpotLight(double lightX, double lightY, double lightZ,
112: double pointAtX, double pointAtY, double pointAtZ,
113: double specularExponent, double limitingConeAngle,
114: Color lightColor) {
115: super (lightColor);
116:
117: this .lightX = lightX;
118: this .lightY = lightY;
119: this .lightZ = lightZ;
120: this .pointAtX = pointAtX;
121: this .pointAtY = pointAtY;
122: this .pointAtZ = pointAtZ;
123: this .specularExponent = specularExponent;
124: this .limitingConeAngle = limitingConeAngle;
125: this .limitingCos = Math.cos(Math.toRadians(limitingConeAngle));
126:
127: S[0] = pointAtX - lightX;
128: S[1] = pointAtY - lightY;
129: S[2] = pointAtZ - lightZ;
130:
131: double invNorm = 1 / Math.sqrt(S[0] * S[0] + S[1] * S[1] + S[2]
132: * S[2]);
133:
134: S[0] *= invNorm;
135: S[1] *= invNorm;
136: S[2] *= invNorm;
137: }
138:
139: /**
140: * @return true if the light is constant over the whole surface
141: */
142: public boolean isConstant() {
143: return false;
144: }
145:
146: /**
147: * Computes the light vector in (x, y, z)
148: *
149: * @param x x-axis coordinate where the light should be computed
150: * @param y y-axis coordinate where the light should be computed
151: * @param z z-axis coordinate where the light should be computed
152: * @param L array of length 3 where the result is stored
153: * @return the intensity factor for this light vector.
154: */
155: public final double getLightBase(final double x, final double y,
156: final double z, final double[] L) {
157: // Light Vector, L
158: double L0 = lightX - x;
159: double L1 = lightY - y;
160: double L2 = lightZ - z;
161:
162: final double invNorm = 1.0 / Math.sqrt(L0 * L0 + L1 * L1 + L2
163: * L2);
164:
165: L0 *= invNorm;
166: L1 *= invNorm;
167: L2 *= invNorm;
168:
169: double LS = -(L0 * S[0] + L1 * S[1] + L2 * S[2]);
170:
171: // copy the work-variables into return-array
172: L[0] = L0;
173: L[1] = L1;
174: L[2] = L2;
175:
176: if (LS <= limitingCos) {
177: return 0;
178: } else {
179: double Iatt = limitingCos / LS;
180: Iatt *= Iatt;
181: Iatt *= Iatt;
182: Iatt *= Iatt;
183: Iatt *= Iatt;
184: Iatt *= Iatt;
185: Iatt *= Iatt; // akin Math.pow(Iatt, 64)
186:
187: Iatt = 1 - Iatt;
188: return Iatt * Math.pow(LS, specularExponent);
189: }
190: }
191:
192: /**
193: * Computes the light vector in (x, y, z)
194: *
195: * @param x x-axis coordinate where the light should be computed
196: * @param y y-axis coordinate where the light should be computed
197: * @param z z-axis coordinate where the light should be computed
198: * @param L array of length 3 where the result is stored,
199: * x,y,z are scaled by light intensity.
200: */
201: public final void getLight(final double x, final double y,
202: final double z, final double[] L) {
203: final double s = getLightBase(x, y, z, L);
204: L[0] *= s;
205: L[1] *= s;
206: L[2] *= s;
207: }
208:
209: /**
210: * computes light vector in (x, y, z).
211: *
212: * @param x x-axis coordinate where the light should be computed
213: * @param y y-axis coordinate where the light should be computed
214: * @param z z-axis coordinate where the light should be computed
215: * @param L array of length 4 where result is stored.
216: * 0,1,2 are x,y,z respectively of light vector (normalized).
217: * 3 is the intensity of the light at this point.
218: */
219: public final void getLight4(final double x, final double y,
220: final double z, final double[] L) {
221: L[3] = getLightBase(x, y, z, L);
222: }
223:
224: public double[][] getLightRow4(double x, double y, final double dx,
225: final int width, final double[][] z,
226: final double[][] lightRow) {
227: double[][] ret = lightRow;
228: if (ret == null)
229: ret = new double[width][4];
230:
231: for (int i = 0; i < width; i++) {
232: getLight4(x, y, z[i][3], ret[i]);
233: x += dx;
234: }
235:
236: return ret;
237: }
238:
239: }
|